From c9b950ac515688b520631427a0bcd8711de2f095 Mon Sep 17 00:00:00 2001 From: Dan Allen Date: Wed, 24 Aug 2022 19:56:39 -0600 Subject: [PATCH] write initial suite of tests --- package-lock.json | 1031 +++++++++++++---- packages/collector-extension/lib/index.js | 170 ++- .../lib/util/run-command.js | 9 +- packages/collector-extension/package.json | 3 + .../test/collector-extension-test.js | 834 ++++++++++++- .../.gen-component-desc-for-ref.js | 19 + .../test-at-root/.gen-component-desc.js | 16 + .../test-at-root/.gen-dirty-worktree.js | 13 + .../test/fixtures/test-at-root/.gen-files.js | 12 + .../fixtures/test-at-root/.gen-for-tag.js | 11 + .../fixtures/test-at-root/.gen-more-files.js | 8 + .../fixtures/test-at-root/.gen-start-page | 3 + .../fixtures/test-at-root/.gen-start-page.bat | 3 + .../fixtures/test-at-root/.gen-start-page.js | 8 + .../test/fixtures/test-at-root/antora.yml | 2 + .../.gen-docs-start-page.js | 8 + .../test-at-start-path/docs/.gen-start-page | 3 + .../docs/.gen-start-page.bat | 3 + .../docs/.gen-start-page.js | 8 + .../test-at-start-path/docs/antora.yml | 2 + .../ROOT/pages/outside-start-path.adoc | 1 + .../test-replace/.gen-replace-start-page.js | 8 + .../test/fixtures/test-replace/antora.yml | 2 + .../modules/ROOT/pages/index.adoc | 3 + packages/collector-test-harness/lib/index.js | 79 +- packages/collector-test-harness/package.json | 4 +- 26 files changed, 1964 insertions(+), 299 deletions(-) create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc-for-ref.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-dirty-worktree.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-files.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-for-tag.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-more-files.js create mode 100755 packages/collector-extension/test/fixtures/test-at-root/.gen-start-page create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.bat create mode 100644 packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.js create mode 100644 packages/collector-extension/test/fixtures/test-at-root/antora.yml create mode 100644 packages/collector-extension/test/fixtures/test-at-start-path/.gen-docs-start-page.js create mode 100755 packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page create mode 100644 packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.bat create mode 100644 packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.js create mode 100644 packages/collector-extension/test/fixtures/test-at-start-path/docs/antora.yml create mode 100644 packages/collector-extension/test/fixtures/test-at-start-path/not-docs/modules/ROOT/pages/outside-start-path.adoc create mode 100644 packages/collector-extension/test/fixtures/test-replace/.gen-replace-start-page.js create mode 100644 packages/collector-extension/test/fixtures/test-replace/antora.yml create mode 100644 packages/collector-extension/test/fixtures/test-replace/modules/ROOT/pages/index.adoc diff --git a/package-lock.json b/package-lock.json index 94416fd..e441d0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,32 @@ "resolved": "packages/collector-test-harness", "link": true }, + "node_modules/@antora/content-aggregator": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.0.tgz", + "integrity": "sha512-5NF9fpWTBbArpPnF+vL2uB2PjmqOcUg24Zj9WOopSw/vy/gknG4xCjzbEU08wWAIYaJotR8VrvpieeGkszIdDw==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "@antora/logger": "3.1.0", + "@antora/user-require-helper": "~2.0", + "braces": "~3.0", + "cache-directory": "~2.0", + "glob-stream": "~7.0", + "hpagent": "~1.0", + "isomorphic-git": "~1.19", + "js-yaml": "~4.1", + "multi-progress": "~4.0", + "picomatch": "~2.3", + "progress": "~2.0", + "should-proxy": "~1.0", + "simple-get": "~4.0", + "vinyl": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@antora/expand-path-helper": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-2.0.0.tgz", @@ -53,6 +79,33 @@ "node": ">=10.17.0" } }, + "node_modules/@antora/logger": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.0.tgz", + "integrity": "sha512-JbYxulCg44mPy9djlWx41rF0ZfY3DUzdihSNMMbE0NrVIaQIWXCEUn02Rp6BL4xwLbJ6hQ0+TsEPRWdjMH5++Q==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0", + "pino": "~8.4", + "pino-pretty": "~9.0", + "sonic-boom": "~3.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/user-require-helper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-2.0.0.tgz", + "integrity": "sha512-5fMfBZfw4zLoFdDAPMQX6Frik90uvfD8rXOA4UpXPOUikkX4uT1Rk6m0/4oi8oS3fcjiIl0k/7Nc+eTxW5TcQQ==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~2.0" + }, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -66,30 +119,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", - "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-compilation-targets": "^7.18.9", "@babel/helper-module-transforms": "^7.18.9", "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", + "@babel/parser": "^7.18.13", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -114,12 +167,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", "dev": true, "dependencies": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -384,9 +437,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", - "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -410,19 +463,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.18.11", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", - "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", + "@babel/generator": "^7.18.13", "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.11", - "@babel/types": "^7.18.10", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -440,9 +493,9 @@ } }, "node_modules/@babel/types": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", - "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.18.10", @@ -583,24 +636,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -657,9 +692,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -702,9 +737,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.5.tgz", - "integrity": "sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ==", + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", "dev": true, "dependencies": { "@types/estree": "*", @@ -737,14 +772,14 @@ "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz", - "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz", + "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.33.0", - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/typescript-estree": "5.33.0", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", "debug": "^4.3.4" }, "engines": { @@ -764,13 +799,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz", - "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0" + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -781,9 +816,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz", - "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -794,13 +829,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz", - "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", - "@typescript-eslint/visitor-keys": "5.33.0", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -821,12 +856,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz", - "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==", + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.33.0", + "@typescript-eslint/types": "5.35.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -843,6 +878,18 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", @@ -1044,6 +1091,21 @@ "node": "*" } }, + "node_modules/async-lock": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.3.2.tgz", + "integrity": "sha512-phnXdS3RP7PPcmP6NWWzWMU0sLTeyvtZCxBPpZdkYE3seGLKSQZs9FrmVO/qwypq98FUtWWUEYxziLkdGk5nnA==", + "dev": true + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1135,6 +1197,18 @@ "semver": "^7.0.0" } }, + "node_modules/cache-directory": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-directory/-/cache-directory-2.0.0.tgz", + "integrity": "sha512-7YKEapH+2Uikde8hySyfobXBqPKULDyHNl/lhKm7cKf/GJFdG/tU/WpLrOg2y9aUrQrWUilYqawFIiGJPS6gDA==", + "dev": true, + "dependencies": { + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1189,9 +1263,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001374", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz", - "integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==", + "version": "1.0.30001383", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001383.tgz", + "integrity": "sha512-swMpEoTp5vDoGBZsYZX7L7nXHe6dsHxi9o6/LKf/f0LukVtnrxly5GVb/fWdCDTqi/yw6Km6tiJ0pmBacm0gbg==", "dev": true, "funding": [ { @@ -1302,6 +1376,12 @@ "node": ">= 6" } }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "dev": true + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1322,6 +1402,65 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/cloneable-readable/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/cloneable-readable/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1340,6 +1479,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -1374,6 +1519,18 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1388,6 +1545,15 @@ "node": ">= 8" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1414,6 +1580,21 @@ "node": ">=0.10.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -1470,6 +1651,12 @@ "node": ">=0.3.1" } }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1521,9 +1708,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.213", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.213.tgz", - "integrity": "sha512-+3DbGHGOCHTVB/Ms63bGqbyC1b8y7Fk86+7ltssB8NQrZtSCvZG6eooSl9U2Q0yw++fL2DpHKOdTU0NVEkFObg==", + "version": "1.4.230", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.230.tgz", + "integrity": "sha512-3pwjAK0qHSDN9+YAF4fJknsSruP7mpjdWzUSruIJD/JCH77pEh0SorEyb3xVaKkfwk2tzjOt2D8scJ0KAdfXLA==", "dev": true }, "node_modules/emoji-regex": { @@ -1739,17 +1926,21 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, "peer": true, "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { @@ -1867,9 +2058,9 @@ "peer": true }, "node_modules/eslint-plugin-n": { - "version": "15.2.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.4.tgz", - "integrity": "sha512-tjnVMv2fiXYMnuiIFI8QMtyUFI42SckEEWvi8h68SWGWshfqO6SSCASy24dGMGAiy7NUk6DZt90DM0iNUsmQ5w==", + "version": "15.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.2.5.tgz", + "integrity": "sha512-8+BYsqiyZfpu6NXmdLOXVUfk8IocpCjpd8nMRRH0A9ulrcemhb2VI9RSJMEy5udx++A/YcVPD11zT8hpFq368g==", "dev": true, "peer": true, "dependencies": { @@ -1877,9 +2068,9 @@ "eslint-plugin-es": "^4.1.0", "eslint-utils": "^3.0.0", "ignore": "^5.1.1", - "is-core-module": "^2.9.0", + "is-core-module": "^2.10.0", "minimatch": "^3.1.2", - "resolve": "^1.10.1", + "resolve": "^1.22.1", "semver": "^7.3.7" }, "engines": { @@ -1893,9 +2084,9 @@ } }, "node_modules/eslint-plugin-promise": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz", - "integrity": "sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz", + "integrity": "sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw==", "dev": true, "peer": true, "engines": { @@ -2026,6 +2217,15 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2044,6 +2244,12 @@ "node": "*" } }, + "node_modules/fast-copy": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-2.1.3.tgz", + "integrity": "sha512-LDzYKNTHhD+XOp8wGMuCkY4eTxFZOOycmpwLBiuF3r3OjOmZnURRD8t2dUAbmKuXGbo/MGggwbSjcBdp8QT0+g==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2090,6 +2296,21 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-redact": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz", + "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -2141,16 +2362,19 @@ } }, "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "peer": true, "dependencies": { - "locate-path": "^2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -2176,9 +2400,9 @@ } }, "node_modules/flatted": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", - "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "node_modules/foreground-child": { @@ -2569,6 +2793,65 @@ "he": "bin/he" } }, + "node_modules/help-me": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.0.1.tgz", + "integrity": "sha512-PLv01Z+OhEPKj2QPYB4kjoCUkopYNPUK3EROlaPIf5bib752fZ+VCvGDAoA+FXo/OwCyLEA4D2e0mX8+Zhcplw==", + "dev": true, + "dependencies": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/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/help-me/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/help-me/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpagent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.0.0.tgz", + "integrity": "sha512-SCleE2Uc1bM752ymxg8QXYGW0TWtAV4ZW3TqH1aOnyi6T6YW2xadCcclm5qeVjvMvfQ2RKNtZxO7uVb9CTPt1A==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -2972,6 +3255,31 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/isomorphic-git": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.19.2.tgz", + "integrity": "sha512-14Tbf3GRFNoXw+fy6ssK7gpDZQxF+NytHmg7p+5L38IAVUafHnfjzJ0ZnEmLz3SAG20wYYyB+HufkRAFRttYxQ==", + "dev": true, + "dependencies": { + "async-lock": "^1.1.0", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -3075,6 +3383,15 @@ "node": ">=8" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3141,17 +3458,18 @@ } }, "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "peer": true, "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -3342,6 +3660,18 @@ "node": ">=8.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3357,8 +3687,16 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", "dev": true, - "peer": true + "dependencies": { + "minimist": "^1.2.5" + } }, "node_modules/mocha": { "version": "10.0.0", @@ -3410,37 +3748,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -3459,45 +3766,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3519,6 +3787,15 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/multi-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multi-progress/-/multi-progress-4.0.0.tgz", + "integrity": "sha512-9zcjyOou3FFCKPXsmkbC3ethv51SFPoA4dJD6TscIp2pUmy26kBDZW6h9XofPELrzseSkuD7r0V+emGEeo39Pg==", + "dev": true, + "peerDependencies": { + "progress": "^2.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -3537,6 +3814,16 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-git-server": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-git-server/-/node-git-server-1.0.0.tgz", + "integrity": "sha512-LdAEExF4N6/RIuAdJe16l1U5OZrw5M1U7B4C4O2PiRVImyaPNTFeTHlj46vGgpjthvrK7z43JKcIPc4r6+j0fA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "through": "^2.3.8" + } + }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -3668,24 +3955,6 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -3771,9 +4040,9 @@ } }, "node_modules/object.assign": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", - "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "peer": true, "dependencies": { @@ -3807,6 +4076,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-exit-leak-free": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", + "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==", + "dev": true + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3863,29 +4138,33 @@ } }, "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "peer": true, "dependencies": { - "p-try": "^1.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "peer": true, "dependencies": { - "p-limit": "^1.1.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { @@ -3901,13 +4180,12 @@ } }, "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "peer": true, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/package-hash": { @@ -3925,6 +4203,12 @@ "node": ">=8" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3938,13 +4222,12 @@ } }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "peer": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/path-is-absolute": { @@ -4007,6 +4290,102 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.4.2.tgz", + "integrity": "sha512-PlXDeGhJZfAuVay+wtlS02s5j8uisQveZExYdAm9MwwxUQSz9R7Q78XtjM2tTa4sa5KJmygimZjZxXXuHgV6ew==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.0.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.1.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", + "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "dev": true, + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", + "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-9.0.1.tgz", + "integrity": "sha512-5gFIIeDu1niFlL0pBACerwDR8Ts+i4gO0W9S0jRoHVvaQluvGOW4cUaDmC+/dSTCoG4VqfOQhP0dwuDLd0qJ6A==", + "dev": true, + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^2.1.1", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", + "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz", + "integrity": "sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==", + "dev": true + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -4071,24 +4450,6 @@ "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4192,6 +4553,21 @@ "node": ">=8" } }, + "node_modules/process-warning": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.0.0.tgz", + "integrity": "sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4240,6 +4616,12 @@ } ] }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4285,6 +4667,15 @@ "node": ">=8.10.0" } }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -4332,6 +4723,15 @@ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4433,6 +4833,21 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-stable-stringify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.5.0.tgz", + "integrity": "sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w==", + "dev": true + }, "node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -4463,6 +4878,19 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4484,6 +4912,12 @@ "node": ">=8" } }, + "node_modules/should-proxy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/should-proxy/-/should-proxy-1.0.4.tgz", + "integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ==", + "dev": true + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -4511,6 +4945,51 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4520,6 +4999,15 @@ "node": ">=8" } }, + "node_modules/sonic-boom": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.2.0.tgz", + "integrity": "sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4546,6 +5034,15 @@ "node": ">=8" } }, + "node_modules/split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4715,6 +5212,21 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thread-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.1.0.tgz", + "integrity": "sha512-5+Pf2Ya31CsZyIPYYkhINzdTZ3guL+jHq7D8lkBybgGcSQIKDbid3NJku3SpCKeE/gACWAccDA/rH2B6doC5aA==", + "dev": true, + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -4888,9 +5400,9 @@ } }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", + "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -4988,6 +5500,23 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vue-eslint-parser": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", @@ -5105,6 +5634,15 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -5215,6 +5753,9 @@ "glob-stream": "~7.0", "js-yaml": "~4.1" }, + "devDependencies": { + "@antora/content-aggregator": "~3.1" + }, "engines": { "node": ">=16.0.0" } @@ -5223,9 +5764,11 @@ "name": "@antora/collector-test-harness", "version": "1.0.0-alpha.0", "devDependencies": { + "@antora/logger": "~3.1", "chai": "~4.3", "chai-fs": "~2.0", - "dirty-chai": "~2.0" + "dirty-chai": "~2.0", + "node-git-server": "~1.0" }, "engines": { "node": ">=16.0.0" diff --git a/packages/collector-extension/lib/index.js b/packages/collector-extension/lib/index.js index 8447db0..2a9a37b 100644 --- a/packages/collector-extension/lib/index.js +++ b/packages/collector-extension/lib/index.js @@ -1,10 +1,12 @@ 'use strict' +const { createHash } = require('crypto') const expandPath = require('@antora/expand-path-helper') const forEach = (write) => new Writable({ objectMode: true, write }) const fs = require('fs') const { promises: fsp } = fs const globStream = require('glob-stream') +const invariably = { false: () => false, void: () => undefined } const ospath = require('path') const runCommand = require('./util/run-command.js') const { pipeline, Writable } = require('stream') @@ -13,46 +15,82 @@ const yaml = require('js-yaml') module.exports.register = function () { this.once('contentAggregated', async ({ playbook, contentAggregate }) => { const git = this.require('@antora/content-aggregator/lib/git') // Q: add dependency on isomorphic-git instead? + const quiet = playbook.runtime?.quiet const cacheDir = getCacheDir(playbook) const workDir = ospath.join(cacheDir, 'collector') // Q: should we use content folder instead? - await fsp.mkdir(workDir, { recursive: true, force: true }) + //await fsp.rm(workDir, { recursive: true, force: true }) // Q: should we try to reuse existing cache? + await fsp.mkdir(workDir, { recursive: true }) const gitCache = {} - for (const bucket of contentAggregate) { - const { ext: { collector } = {}, files: filesInBucket, origins } = bucket - if (!collector) continue - // TODO: support multiple entries - const { run: { dir: runDir, command, local } = {}, scan: { dir: scanDir, glob } = {} } = collector - // TODO: run collector per origin - const { gitdir, refname, worktree, startPath } = origins[0] - const worktreeDir = worktree || ospath.join(workDir, ospath.basename(gitdir, '.git')) - const expandPathContext = { base: worktreeDir, cwd: worktreeDir, dot: ospath.join(worktreeDir, startPath) } - const absScanDir = typeof scanDir === 'string' ? expandPath(scanDir, expandPathContext) : undefined - if (worktree) { - if (absScanDir) await fsp.rm(absScanDir, { force: true, recursive: true }) - } else { - const cache = gitCache[gitdir] || (gitCache[gitdir] = {}) - await removeUntrackedFiles(git, { fs, cache, dir: worktreeDir, gitdir }) - await git.checkout({ fs, cache, dir: worktreeDir, gitdir, ref: refname, force: true }) - } - if (command) { - const cwd = typeof runDir === 'string' ? expandPath(runDir, expandPathContext) : worktreeDir - command.startsWith('./') - ? await runCommand(command.slice(2), [], { output: true, local: true, cwd }) - : await runCommand(command, [], { output: true, local, cwd }) - } - if (!absScanDir) continue - for (const file of await srcFs(globStream, absScanDir, glob)) { - let matchingFile - if (file.path === 'antora.yml') { - const generated = yaml.load(file.contents) - delete generated.version - delete generated.prerelease - Object.assign(bucket, generated) - } else if ((matchingFile = filesInBucket.find((it) => it.path === file.path))) { - // TODO: update stat - matchingFile.contents = file.contents + for (const componentVersionBucket of contentAggregate) { + const { files: filesInBucket, origins = [] } = componentVersionBucket + for (const { url, gitdir, refname, reftype, remote, worktree, startPath, descriptor = {} } of origins) { + const collectorConfig = descriptor['ext:collector'] || [] + if (Array.isArray(collectorConfig) && !collectorConfig.length) continue + const worktreeDir = worktree || ospath.join(workDir, generateWorktreeFolderName({ url, gitdir, worktree })) + const expandPathContext = { base: worktreeDir, cwd: worktreeDir, dot: ospath.join(worktreeDir, startPath) } + const scanDirs = new Set() + const collectors = (Array.isArray(collectorConfig) ? collectorConfig : [collectorConfig]).map((collector) => { + const { run: runConfig = {}, scan: scanConfig = [] } = collector + return { + run: { + ...runConfig, + cwd: typeof runConfig.dir === 'string' ? expandPath(runConfig.dir, expandPathContext) : worktreeDir, + }, + scan: (Array.isArray(scanConfig) ? scanConfig : [scanConfig]).reduce((accum, scan) => { + if (typeof scan.dir === 'string') { + const dir = expandPath(scan.dir, expandPathContext) + scanDirs.add(dir) + accum.push({ ...scan, dir }) + } + return accum + }, []), + } + }) + if (worktree) { + for (const scanDir of scanDirs) await fsp.rm(scanDir, { force: true, recursive: true }) } else { - filesInBucket.push(file) + const cache = gitCache[gitdir] || (gitCache[gitdir] = {}) + const ref = `refs/${reftype === 'branch' ? 'head' : reftype}s/${refname}` + // Q: if repo is local, should we operate on a clone instead? + await prepareWorktree(git, { fs, cache, dir: worktreeDir, gitdir, ref, remote, bare: worktree === undefined }) + } + for (const { run, scan: scans } of collectors) { + const { cwd, command, local } = run + if (command) { + let cmd = command + const cmdOpts = { cwd, local, output: true, quiet } + if (cmd.startsWith('./')) { + cmd = cmd.slice(2) + cmdOpts.local = true + } else if (cmd.startsWith('node ') ? (cmd = cmd.slice(5)) : !local && cmd.split(' ')[0].endsWith('.js')) { + cmd = process.execPath + ' ' + cmd + } + try { + await runCommand(cmd, [], cmdOpts) + } catch (err) { + const loc = worktree || url + const flag = worktree ? ' ' : remote && worktree === false ? ` ` : '' + const pathInfo = startPath ? ` | start path: ${startPath}` : '' + const ctx = ` in ${loc} (${reftype}: ${refname}${flag}${pathInfo})` + throw Object.assign(err, { message: `(@antora/collector-extension): ${err.message.replace(/$/m, ctx)}` }) + } + } + for (const scan of scans) { + for (const file of await srcFs(scan.dir, scan.glob)) { + let existingFile + if (file.path === 'antora.yml') { + const generated = yaml.load(file.contents) + Object.assign(componentVersionBucket, generated) + if (!('version' in generated)) delete componentVersionBucket.version + if (!('prerelease' in generated)) delete componentVersionBucket.prerelease + } else if ((existingFile = filesInBucket.find((it) => it.path === file.path))) { + // TODO: update stat + existingFile.contents = file.contents + } else { + filesInBucket.push(file) + } + } + } } } } @@ -60,15 +98,65 @@ module.exports.register = function () { }) } +async function prepareWorktree (git, repo) { + const { dir, gitdir, ref, remote = 'origin', bare } = repo + delete repo.remote + const currentIndexPath = ospath.join(gitdir, 'index') + const currentIndex = await fsp.readFile(currentIndexPath).catch(invariably.void) + const worktreeGitdir = ospath.join(dir, '.git') + const worktreeIndexPath = ospath.join(worktreeGitdir, 'index') + try { + let force + if (await isDirectory(worktreeGitdir)) { + force = false + await fsp.cp(worktreeIndexPath, currentIndexPath) + await removeUntrackedFiles(git, repo) + } else { + force = true + await fsp.access(dir).then(() => fsp.rm(dir, { recursive: true, force: true }), invariably.void) + } + let head + if (ref.startsWith('refs/heads')) { + head = `ref: ${ref}` + const branchName = ref.substr(11) + if (bare || !(await git.listBranches(repo)).includes(branchName)) { + await git + .resolveRef({ ...repo, ref: `refs/remotes/${remote}/${branchName}` }) + .then((sha) => fsp.writeFile(ospath.join(gitdir, ref), `${sha}\n`, 'utf8')) + } + } else { + head = await git.resolveRef(repo) + } + await git.checkout({ ...repo, force, noUpdateHead: true, track: false }) + await fsp.mkdir(worktreeGitdir, { recursive: true }) + await fsp.writeFile(ospath.join(worktreeGitdir, 'commondir'), `${gitdir}\n`, 'utf8') + await fsp.writeFile(ospath.join(worktreeGitdir, 'HEAD'), `${head}\n`, 'utf8') + await fsp.cp(currentIndexPath, worktreeIndexPath) + } finally { + if (currentIndex) await fsp.writeFile(currentIndexPath, currentIndex) + } +} + +function generateWorktreeFolderName ({ url, gitdir, worktree }) { + if (worktree === undefined) return ospath.basename(gitdir, '.git') + const hash = createHash('sha1') + hash.update(url) + return [url.substr(url.lastIndexOf('/') + 1), hash.digest('hex')].join('-') +} + +function isDirectory (path_) { + return fsp.stat(path_).then((stat) => stat.isDirectory(), invariably.false) +} + function getCacheDir (playbook) { return expandPath(playbook.runtime.cacheDir || './cache/antora', { dot: playbook.dir }) } -function srcFs (globStream, dir, glob = '**/*') { +function srcFs (dir, glob = '**/*') { return new Promise((resolve, reject) => { const files = [] pipeline( - globStream(glob, { cwd: dir, nodir: true, nomount: true, nosort: true, nounique: true }), + globStream(glob, { allowEmpty: true, cwd: dir, nodir: true, nomount: true, nosort: true, nounique: true }), forEach(({ path: abspathPosix }, _, done) => { const abspath = ospath.sep === '\\' ? ospath.normalize(abspathPosix) : abspathPosix const relpath = abspath.substr(dir.length + 1) @@ -100,10 +188,10 @@ function srcFs (globStream, dir, glob = '**/*') { } async function removeUntrackedFiles (git, repo) { - const trees = [git.TREE({}), git.WORKDIR()] - const map = async (filepath, [tEntry, wEntry]) => { + const trees = [git.STAGE({}), git.WORKDIR()] + const map = async (filepath, [sEntry, wEntry]) => { if (filepath === '.git') return null - if (filepath !== '.' && tEntry == null) { + if (filepath !== '.' && sEntry == null) { await fsp.rm(ospath.join(repo.dir, filepath), { recursive: true }) return null } diff --git a/packages/collector-extension/lib/util/run-command.js b/packages/collector-extension/lib/util/run-command.js index 59c2574..d3682f7 100644 --- a/packages/collector-extension/lib/util/run-command.js +++ b/packages/collector-extension/lib/util/run-command.js @@ -11,9 +11,8 @@ const DBL_QUOTE_RX = /"/g class LazyReadable extends PassThrough { constructor (fn, options) { super(options) - const _read = this._read this._read = function () { - this._read = _read.bind(this) + delete this._read // restores original method fn.call(this, options).on('error', this.emit.bind(this, 'error')).pipe(this) return this._read.apply(this, arguments) } @@ -37,7 +36,7 @@ const shellEscape = IS_WIN async function runCommand (cmd, argv = [], opts = {}) { if (!cmd) throw new TypeError('Command not specified') const cmdv = cmd.split(' ').map(shellEscape) - const { input, output, implicitStdin, local, ...spawnOpts } = opts + const { input, output, quiet, implicitStdin, local, ...spawnOpts } = opts if (input) input instanceof Buffer ? implicitStdin || argv.push('-') : argv.push(input) if (IS_WIN) Object.assign(spawnOpts, { shell: true, windowsHide: true }) if (local && !IS_WIN) cmdv[0] = `./${cmdv[0]}` @@ -60,8 +59,8 @@ async function runCommand (cmd, argv = [], opts = {}) { } }) ps.on('error', (err) => reject(err.code === 'ENOENT' ? new Error(`Command not found: ${cmdv.join(' ')}`) : err)) - ps.stdout.on('data', (data) => (output ? process.stdout.write(data) : stdout.push(data))) - ps.stderr.on('data', (data) => stderr.push(data)) + ps.stdout.on('data', (data) => (output ? !quiet && process.stdout.write(data) : stdout.push(data))) + ps.stderr.on('data', (data) => !quiet && stderr.push(data)) try { input instanceof Buffer ? ps.stdin.end(input) : ps.stdin.end() } catch (err) { diff --git a/packages/collector-extension/package.json b/packages/collector-extension/package.json index 36319b3..5e5de8c 100644 --- a/packages/collector-extension/package.json +++ b/packages/collector-extension/package.json @@ -32,6 +32,9 @@ "glob-stream": "~7.0", "js-yaml": "~4.1" }, + "devDependencies": { + "@antora/content-aggregator": "~3.1" + }, "keywords": [ "antora", "antora-extension", diff --git a/packages/collector-extension/test/collector-extension-test.js b/packages/collector-extension/test/collector-extension-test.js index 2a733a4..604dded 100644 --- a/packages/collector-extension/test/collector-extension-test.js +++ b/packages/collector-extension/test/collector-extension-test.js @@ -1,16 +1,836 @@ /* eslint-env mocha */ 'use strict' -const { expect } = require('@antora/collector-test-harness') +const { + captureStdout, + closeServer, + expect, + heredoc, + startGitServer, + trapAsyncError, + updateYamlFile, +} = require('@antora/collector-test-harness') +const aggregateContent = require('@antora/content-aggregator') +const { createHash } = require('crypto') +const fs = require('fs') +const { promises: fsp } = fs +const { isAsyncFunction: isAsync } = require('util').types +const git = require('@antora/content-aggregator/git') +const ospath = require('path') + +const FIXTURES_DIR = ospath.join(__dirname, 'fixtures') +const WORK_DIR = ospath.join(__dirname, 'work') +const CACHE_DIR = ospath.join(WORK_DIR, 'cache') +const REPOS_DIR = ospath.join(WORK_DIR, 'repos') describe('collector extension', () => { - it('should be able to require extension', () => { - const exports = require('@antora/collector-extension') - expect(exports).to.be.instanceOf(Object) - expect(exports.register).to.be.instanceOf(Function) + let gitServer + let gitServerPort + + const cleanWorkDir = async (opts = {}) => { + await fsp.rm(WORK_DIR, { recursive: true, force: true }) + if (opts.create) await fsp.mkdir(WORK_DIR, { recursive: true }) + } + + const getCollectorCacheDir = () => { + return ospath.join(CACHE_DIR, 'collector') + } + + const getCollectorWorktree = (origin) => { + let folderName + if (origin.worktree === undefined) { + folderName = ospath.basename(origin.gitdir, '.git') + } else { + const url = origin.url + const hash = createHash('sha1') + hash.update(url) + folderName = url.substr(url.lastIndexOf('/') + 1) + '-' + hash.digest('hex') + } + return ospath.join(getCollectorCacheDir(), folderName) + } + + before(async () => { + await cleanWorkDir({ create: true }) + ;[gitServer, gitServerPort] = await startGitServer(REPOS_DIR) + }) + + after(async () => { + await closeServer(gitServer.server) + await fsp.rm(WORK_DIR, { recursive: true, force: true }) }) - it('should have tests', () => { - expect(true).to.be.true() + afterEach(async () => { + await cleanWorkDir() + }) + + describe('bootstrap', () => { + it('should be able to require extension', () => { + const exports = require('@antora/collector-extension') + expect(exports).to.be.instanceOf(Object) + expect(exports.register).to.be.instanceOf(Function) + }) + }) + + describe('integration', () => { + const ext = require('@antora/collector-extension') + + const createGeneratorContext = () => ({ + require: () => git, + once (eventName, fn) { + this[eventName] = fn + }, + }) + + const createRepository = async ({ repoName, fixture = repoName, branches, tags, startPath, collectorConfig }) => { + const repo = { dir: ospath.join(REPOS_DIR, repoName), fs } + await fsp.cp(ospath.join(FIXTURES_DIR, fixture), repo.dir, { recursive: true }) + if (collectorConfig) { + const antoraYmlPath = ospath.join(repo.dir, startPath || '', 'antora.yml') + await updateYamlFile(antoraYmlPath, { 'ext:collector': collectorConfig }) + } + await git.init({ ...repo, defaultBranch: 'main' }) + await git + .statusMatrix(repo) + .then((status) => + Promise.all( + status.map(([filepath, _, worktreeStatus]) => + worktreeStatus === 0 ? git.remove({ ...repo, filepath }) : git.add({ ...repo, filepath }) + ) + ) + ) + await git.commit({ ...repo, author: { name: 'Tester', email: 'tester@example.org' }, message: 'initial import' }) + if (branches) { + for (const branch of branches) await git.branch({ ...repo, ref: branch }) + } + if (tags) { + for (const tag of tags) await git.tag({ ...repo, ref: tag }) + } + repo.url = `http://localhost:${gitServerPort}/${repoName}/.git` + return repo + } + + const runScenario = async ({ repoName, branches, tags, startPath, local, collectorConfig, before, after }) => { + const repo = await createRepository({ repoName, branches, tags, startPath, collectorConfig }) + const playbook = { + runtime: { cacheDir: CACHE_DIR, quiet: true }, + content: { + sources: [ + { + url: local ? repo.dir : repo.url, + startPath, + branches: branches || 'main', + tags, + }, + ], + }, + } + const contentAggregate = await aggregateContent(playbook) + if (before) isAsync(before) ? await before(contentAggregate, playbook) : before(contentAggregate, playbook) + const generatorContext = createGeneratorContext() + ext.register.call(generatorContext) + await generatorContext.contentAggregated({ playbook, contentAggregate }) + if (after) isAsync(after) ? await after(contentAggregate) : after(contentAggregate) + } + + it('should not allocate worktree for reference without worktree if collector config is not specified', async () => { + await runScenario({ + repoName: 'test-at-root', + before: async (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.files).to.be.empty() + const worktree = getCollectorWorktree(bucket.origins[0]) + await fsp.mkdir(ospath.dirname(worktree), { recursive: true }) + await fsp.writeFile(worktree, Buffer.alloc(0)) + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.be.empty() + }, + }) + }) + + it('should run specified command in temporary worktree and collect files in scan dir', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should populate properties of scanned file', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + const expectedAbsPath = ospath.join( + getCollectorWorktree(contentAggregate[0].origins[0]), + 'build/modules/ROOT/pages/index.adoc' + ) + expect(contentAggregate[0].files[0]).to.have.property('stat') + expect(contentAggregate[0].files[0].src).to.eql({ + path: 'modules/ROOT/pages/index.adoc', + basename: 'index.adoc', + stem: 'index', + extname: '.adoc', + abspath: expectedAbsPath, + }) + }, + }) + }) + + it('should update component metadata from antora.yml file, if found', async () => { + const collectorConfig = { + run: { command: 'node .gen-component-desc.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.version).to.equal('main') + expect(bucket.files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.version).to.equal('1.0.0') + expect(bucket.title).to.equal('Test') + expect(bucket.files).to.be.empty() + expect(bucket).to.have.nested.property('asciidoc.attributes.url-api', 'https://api.example.org') + const expectedScriptDirname = getCollectorWorktree(bucket.origins[0]) + expect(bucket.asciidoc.attributes['script-dirname']).to.equal(expectedScriptDirname) + }, + }) + }) + + // TODO verify that stat is updated too + it('should update contents of existing page', async () => { + const collectorConfig = { + run: { command: 'node .gen-replace-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-replace', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.have.lengthOf(1) + const expectedContents = heredoc` + = Stub Start Page + + This page is just a stub. + ` + expect(contentAggregate[0].files[0].contents.toString()).to.equal(expectedContents + '\n') + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + const expectedContents = heredoc` + = Real Start Page + + This is the real deal. + ` + expect(contentAggregate[0].files[0].contents.toString()).to.equal(expectedContents + '\n') + }, + }) + }) + + it('should run specified command in start path of temporary worktree and collect files in scan dir', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js', dir: '.' }, + scan: { dir: './build' }, + } + await runScenario({ + repoName: 'test-at-start-path', + startPath: 'docs', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should run specified command from root of temporary worktree and collect files in scan dir', async () => { + const collectorConfig = { + run: { command: 'node .gen-docs-start-page.js' }, + scan: { dir: 'build/docs' }, + } + await runScenario({ + repoName: 'test-at-start-path', + startPath: 'docs', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should prepend node to command specified as a JavaScript file', async () => { + const collectorConfig = { + run: { command: '.gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should run specified local executable command if command begins with ./', async () => { + const collectorConfig = { + run: { command: './.gen-start-page' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should run specified local executable command if local option is true', async () => { + const collectorConfig = { + run: { command: '.gen-start-page', local: true }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should run specified command from content root if dir option is .', async () => { + const collectorConfig = { + run: { command: '.gen-start-page', local: true, dir: '.' }, + scan: { dir: './build' }, + } + await runScenario({ + repoName: 'test-at-start-path', + startPath: 'docs', + collectorConfig, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/index.adoc') + }, + }) + }) + + it('should not collect files if scan key is not specified', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.be.empty() + }, + }) + }) + + it('should collect files without running command if only scan key is specified', async () => { + const collectorConfig = { + scan: { dir: 'not-docs' }, + } + await runScenario({ + repoName: 'test-at-start-path', + startPath: 'docs', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + expect(contentAggregate[0].files[0].path).to.equal('modules/ROOT/pages/outside-start-path.adoc') + }, + }) + }) + + it('should collect files from multiple scan dirs', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js', dir: '.' }, + scan: [{ dir: './build' }, { dir: 'not-docs' }], + } + await runScenario({ + repoName: 'test-at-start-path', + startPath: 'docs', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(2) + expect(contentAggregate[0].files.map((it) => it.path)).to.have.members([ + 'modules/ROOT/pages/index.adoc', + 'modules/ROOT/pages/outside-start-path.adoc', + ]) + }, + }) + }) + + it('should process each collector entry', async () => { + const collectorConfig = [ + { + run: { command: 'node .gen-files.js' }, + scan: { dir: 'build' }, + }, + { + run: { command: 'node .gen-component-desc.js' }, + scan: { dir: 'build', glob: 'antora.yml' }, + }, + ] + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].version).to.eql('main') + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.version).to.equal('1.0.0') + expect(bucket.files).to.have.lengthOf(3) + expect(bucket.files.map((it) => it.path)).to.have.members([ + 'modules/ROOT/pages/index.adoc', + 'modules/ROOT/partials/summary.adoc', + 'modules/ROOT/examples/ack.rb', + ]) + expect( + contentAggregate[0].files.find((it) => it.path === 'modules/ROOT/pages/index.adoc').contents.toString() + ).to.include('= The Start Page') + }, + }) + }) + + it('should not clean worktree between collector entries', async () => { + const collectorConfig = [ + { + run: { command: 'node .gen-files.js' }, + }, + { + run: { command: 'node .gen-component-desc.js' }, + }, + { + run: { command: 'node .gen-start-page.js' }, + scan: [ + { dir: 'build', glob: 'antora.yml' }, + { dir: 'build', glob: 'modules/**/*' }, + ], + }, + ] + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].version).to.eql('main') + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.version).to.equal('1.0.0') + expect(bucket.files).to.have.lengthOf(3) + expect(bucket.files.map((it) => it.path)).to.have.members([ + 'modules/ROOT/pages/index.adoc', + 'modules/ROOT/partials/summary.adoc', + 'modules/ROOT/examples/ack.rb', + ]) + expect( + contentAggregate[0].files.find((it) => it.path === 'modules/ROOT/pages/index.adoc').contents.toString() + ).to.include('= Start Page') + }, + }) + }) + + it('should only collect files that match scan glob', async () => { + const collectorConfig = { + run: { command: 'node .gen-files.js' }, + scan: { dir: 'build', glob: '**/*.adoc' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(2) + const paths = contentAggregate[0].files.map((it) => it.path) + expect(paths).to.have.members(['modules/ROOT/pages/index.adoc', 'modules/ROOT/partials/summary.adoc']) + }, + }) + }) + + it('should support an array of scan globs with inclusions and exclusions', async () => { + const collectorConfig = { + run: { command: 'node .gen-files.js' }, + scan: { dir: 'build', glob: ['**/*.adoc', '!modules/*/partials/**/*.adoc', 'modules/**/*.rb'] }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(2) + const paths = contentAggregate[0].files.map((it) => it.path) + expect(paths).to.have.members(['modules/ROOT/pages/index.adoc', 'modules/ROOT/examples/ack.rb']) + }, + }) + }) + + it('should create work dir under cache for collector', async () => { + await fsp.mkdir(CACHE_DIR, { recursive: true }) + await fsp.writeFile(getCollectorCacheDir(), Buffer.alloc(0)) + expect(await trapAsyncError(() => runScenario({ repoName: 'test-at-root' }))).to.throw('file already exists') + }) + + it('should remove work dir under cache for collector after run', async () => { + await runScenario({ repoName: 'test-at-root' }) + expect(getCollectorCacheDir()).to.not.be.a.path() + }) + + it('should reuse worktree if available', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + local: true, + collectorConfig, + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files).to.have.lengthOf(1) + const worktree = contentAggregate[0].origins[0].worktree + expect(ospath.join(worktree, 'build')).to.be.a.directory() + expect(ospath.join(worktree, 'build/modules/ROOT/pages/index.adoc')).to.be.a.file() + }, + }) + }) + + it('should clean scan dir in worktree before running command(s)', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + local: true, + collectorConfig, + before: async (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files).to.be.empty() + const worktree = contentAggregate[0].origins[0].worktree + const residualPagePath = ospath.join(worktree, 'build/modules/ROOT/pages/residual-page.adoc') + await fsp.mkdir(ospath.dirname(residualPagePath), { recursive: true }) + await fsp.writeFile(residualPagePath, '= Residual Page', 'utf8') + }, + after: (contentAggregate) => { + expect(contentAggregate[0].files.map((it) => it.path)).to.not.include('modules/ROOT/pages/residual-page.adoc') + }, + }) + }) + + it('should run specified command in temporary worktree if repository is local and reference is not worktree', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + local: true, + branches: ['other'], + after: (contentAggregate) => { + const bucket = contentAggregate[0] + const expectedAbsPath = ospath.join( + getCollectorWorktree(bucket.origins[0]), + 'build/modules/ROOT/pages/index.adoc' + ) + expect(bucket.files).to.have.lengthOf(1) + expect(bucket.files[0].src.abspath).to.equal(expectedAbsPath) + }, + }) + }) + + it('should run specified command in each branch that defines collector config', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + local: true, + branches: ['v1.0.x', 'v2.0.x'], + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + contentAggregate.forEach((bucket) => { + expect(bucket.origins[0].refname).to.be.oneOf(['v1.0.x', 'v2.0.x']) + const expectedAbsPath = ospath.join( + getCollectorWorktree(bucket.origins[0]), + 'build/modules/ROOT/pages/index.adoc' + ) + expect(bucket.files).to.have.lengthOf(1) + expect(bucket.files[0].src.abspath).to.equal(expectedAbsPath) + }) + }, + }) + }) + + it('should run specified command in tag that defines collector config', async () => { + const collectorConfig = { + run: { command: 'node .gen-for-tag.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + branches: [], + tags: ['v1.0.1'], + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].origins[0].refname).to.equal('v1.0.1') + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + const bucket = contentAggregate[0] + expect(bucket.version).to.equal('1.0.1') + const expectedAbsPath = ospath.join( + getCollectorWorktree(bucket.origins[0]), + 'build/modules/ROOT/pages/v1.0.1-release.adoc' + ) + expect(bucket.files).to.have.lengthOf(1) + expect(bucket.files[0].src.abspath).to.equal(expectedAbsPath) + }, + }) + }) + + it('should run command inside worktree for both branches and tags in same repository', async () => { + const collectorConfig = { + run: { command: 'node .gen-component-desc-for-ref.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + branches: ['v1.0.x'], + tags: ['v1.0.1'], + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + expect(contentAggregate.map((it) => it.origins[0].refname)).to.have.members(['v1.0.1', 'v1.0.x']) + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + const branchBucket = contentAggregate.find((it) => it.origins[0].reftype === 'branch') + expect(branchBucket.version).to.equal('1.0') + expect(branchBucket.prerelease).to.be.true() + const tagBucket = contentAggregate.find((it) => it.origins[0].reftype === 'tag') + expect(tagBucket.version).to.equal('1.0.1') + expect(tagBucket.prerelease).to.be.false() + }, + }) + }) + + it('should not modify index of local repository when checking out ref to worktree', async () => { + const collectorConfig = { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + } + let expectedIndex + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + local: true, + branches: ['v1.0.x'], + before: async (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expectedIndex = await fsp.readFile(ospath.join(contentAggregate[0].origins[0].gitdir, 'index'), 'utf8') + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(1) + expect(ospath.join(contentAggregate[0].origins[0].gitdir, 'index')).to.have.contents(expectedIndex) + }, + }) + }) + + it('should remove untracked changes when switching worktrees for same repository', async () => { + const collectorConfig = { + run: { command: 'node .gen-dirty-worktree.js' }, + scan: { dir: 'build' }, + } + await runScenario({ + repoName: 'test-at-root', + collectorConfig, + branches: ['v1.0.x', 'v2.0.x'], + before: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + const [bucket1, bucket2] = contentAggregate + expect(bucket1).to.have.property('version', 'v1.0.x') + expect(bucket2).to.have.property('version', 'v2.0.x') + }, + after: (contentAggregate) => { + expect(contentAggregate).to.have.lengthOf(2) + const [bucket1, bucket2] = contentAggregate + expect(bucket1).to.have.property('version', '1.0') + expect(bucket1.files).to.have.lengthOf(1) + expect(bucket1.files[0].path).to.equal('modules/ROOT/pages/v1.0.x-release.adoc') + expect(bucket2).to.have.property('version', '2.0') + expect(bucket2.files).to.have.lengthOf(1) + expect(bucket2.files[0].path).to.equal('modules/ROOT/pages/v2.0.x-release.adoc') + }, + }) + }) + + it('should send output from command to stdout by default', async () => { + const collectorConfig = { run: { command: 'node -p "start\\nfinish"' } } + const stdout = await captureStdout(() => + runScenario({ + repoName: 'test-at-root', + collectorConfig, + before: (_, playbook) => { + delete playbook.runtime.quiet + }, + }) + ) + expect(stdout).to.equal('start\nfinish\n') + }) + + it('should not send output from command to stdout by default if quiet is set', async () => { + const collectorConfig = { run: { command: 'node -p "start\\nfinish"' } } + const stdout = await captureStdout(() => runScenario({ repoName: 'test-at-root', collectorConfig })) + expect(stdout).to.be.empty() + }) + + it('should throw error if command is not found', async () => { + const collectorConfig = { run: { command: 'no-such-command' } } + const expectedMessage = + '(@antora/collector-extension): Command not found: no-such-command in ' + + `http://localhost:${gitServerPort}/test-at-root/.git (branch: main)` + expect(await trapAsyncError(() => runScenario({ repoName: 'test-at-root', collectorConfig }))).to.throw( + Error, + expectedMessage + ) + }) + + it('should throw error if command is not found for origin with start path', async () => { + const collectorConfig = { run: { command: 'no-such-command' } } + const expectedMessage = + '(@antora/collector-extension): Command not found: no-such-command in ' + + `http://localhost:${gitServerPort}/test-at-start-path/.git (branch: main | start path: docs)` + expect( + await trapAsyncError(() => runScenario({ repoName: 'test-at-start-path', collectorConfig, startPath: 'docs' })) + ).to.throw(Error, expectedMessage) + }) + + it('should throw error if command is not found when using local worktree', async () => { + const collectorConfig = { run: { command: 'no-such-command' } } + const expectedMessage = + '(@antora/collector-extension): Command not found: no-such-command in ' + + `${ospath.join(REPOS_DIR, 'test-at-root')} (branch: main )` + expect( + await trapAsyncError(() => runScenario({ repoName: 'test-at-root', collectorConfig, local: true })) + ).to.throw(Error, expectedMessage) + }) + + it('should run collector per origin in which it is defined', async () => { + const repo1 = await createRepository({ + repoName: 'test-at-root-1', + fixture: 'test-at-root', + collectorConfig: { + run: { command: 'node .gen-start-page.js' }, + scan: { dir: 'build' }, + }, + }) + const repo2 = await createRepository({ repoName: 'test-at-root-2', fixture: 'test-at-root' }) + const repo3 = await createRepository({ + repoName: 'test-at-root-3', + fixture: 'test-at-root', + collectorConfig: { + run: { command: 'node .gen-more-files.js' }, + scan: { dir: 'build' }, + }, + }) + const playbook = { + runtime: { cacheDir: CACHE_DIR, quiet: true }, + content: { + sources: [ + { url: repo1.url, branches: 'main' }, + { url: repo2.url, branches: 'main' }, + { url: repo3.url, branches: 'main' }, + ], + }, + } + const contentAggregate = await aggregateContent(playbook) + const generatorContext = createGeneratorContext() + ext.register.call(generatorContext) + await generatorContext.contentAggregated({ playbook, contentAggregate }) + expect(contentAggregate).to.have.lengthOf(1) + expect(contentAggregate[0].files.map((it) => it.path)).to.have.members([ + 'modules/ROOT/pages/index.adoc', + 'modules/more/pages/index.adoc', + ]) + }) }) }) diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc-for-ref.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc-for-ref.js new file mode 100644 index 0000000..4f3c0a9 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc-for-ref.js @@ -0,0 +1,19 @@ +'use strict' + +const { promises: fsp } = require('fs') +const { spawnSync } = require('child_process') + +;(async () => { + let version, prerelease + const branch = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).stdout.toString().trimRight() + if (branch === 'HEAD') { + version = spawnSync('git', ['describe', '--tags']).stdout.toString().trimRight() + prerelease = false + } else { + version = branch.replace('.x', '') + prerelease = true + } + await fsp.mkdir('build', { recursive: true }) + const antoraYml = `name: test\nversion: '${version.substr(1)}'\nprerelease: ${prerelease}\ntitle: Test\n` + await fsp.writeFile('build/antora.yml', antoraYml, 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc.js new file mode 100644 index 0000000..121e49c --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-component-desc.js @@ -0,0 +1,16 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build', { recursive: true }) + const antoraYml = + 'name: test\n' + + 'version: 1.0.0\n' + + 'title: Test\n' + + 'asciidoc:\n' + + ' attributes:\n' + + ' url-api: https://api.example.org\n' + + ` script-dirname: ${__dirname}\n` + await fsp.writeFile('build/antora.yml', antoraYml, 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-dirty-worktree.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-dirty-worktree.js new file mode 100644 index 0000000..80dcac4 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-dirty-worktree.js @@ -0,0 +1,13 @@ +'use strict' + +const { promises: fsp } = require('fs') +const { spawnSync } = require('child_process') + +;(async () => { + const branch = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD']).stdout.toString().trimRight() + await fsp.writeFile('antora.yml', `name: test\nversion: '${branch.substr(1).replace('.x', '')}'\n`, 'utf8') + await fsp.writeFile(`untracked-${branch}.txt`, 'untracked', 'utf8') + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/antora.yml', `name: test\nversion: '${branch.substr(1).replace('.x', '')}'\n`, 'utf8') + await fsp.writeFile(`build/modules/ROOT/pages/${branch}-release.adoc`, '= Branch-Specific Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-files.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-files.js new file mode 100644 index 0000000..3724ace --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-files.js @@ -0,0 +1,12 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/pages/index.adoc', '= The Start Page', 'utf8') + await fsp.mkdir('build/modules/ROOT/partials', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/partials/summary.adoc', 'The summary.', 'utf8') + await fsp.mkdir('build/modules/ROOT/examples', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/examples/ack.rb', 'puts 1', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-for-tag.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-for-tag.js new file mode 100644 index 0000000..0d88606 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-for-tag.js @@ -0,0 +1,11 @@ +'use strict' + +const { promises: fsp } = require('fs') +const { spawnSync } = require('child_process') + +;(async () => { + const tag = spawnSync('git', ['describe', '--tags']).stdout.toString().trimRight() + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/antora.yml', `name: test\nversion: '${tag.substr(1)}'\n`, 'utf8') + await fsp.writeFile(`build/modules/ROOT/pages/${tag}-release.adoc`, '= Tag-Specific Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-more-files.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-more-files.js new file mode 100644 index 0000000..49cc999 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-more-files.js @@ -0,0 +1,8 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/modules/more/pages', { recursive: true }) + await fsp.writeFile('build/modules/more/pages/index.adoc', '= Another Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page new file mode 100755 index 0000000..5ff6595 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page @@ -0,0 +1,3 @@ +#!/bin/bash + +node .gen-start-page.js diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.bat b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.bat new file mode 100644 index 0000000..580e952 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.bat @@ -0,0 +1,3 @@ +@echo off + +node .gen-start-page.js diff --git a/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.js b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.js new file mode 100644 index 0000000..b290212 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/.gen-start-page.js @@ -0,0 +1,8 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/pages/index.adoc', '= Start Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-root/antora.yml b/packages/collector-extension/test/fixtures/test-at-root/antora.yml new file mode 100644 index 0000000..e35bef6 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-root/antora.yml @@ -0,0 +1,2 @@ +name: test +version: true diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/.gen-docs-start-page.js b/packages/collector-extension/test/fixtures/test-at-start-path/.gen-docs-start-page.js new file mode 100644 index 0000000..0230770 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/.gen-docs-start-page.js @@ -0,0 +1,8 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/docs/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/docs/modules/ROOT/pages/index.adoc', '= Start Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page new file mode 100755 index 0000000..5ff6595 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page @@ -0,0 +1,3 @@ +#!/bin/bash + +node .gen-start-page.js diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.bat b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.bat new file mode 100644 index 0000000..580e952 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.bat @@ -0,0 +1,3 @@ +@echo off + +node .gen-start-page.js diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.js b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.js new file mode 100644 index 0000000..b290212 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/docs/.gen-start-page.js @@ -0,0 +1,8 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/pages/index.adoc', '= Start Page', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/docs/antora.yml b/packages/collector-extension/test/fixtures/test-at-start-path/docs/antora.yml new file mode 100644 index 0000000..e35bef6 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/docs/antora.yml @@ -0,0 +1,2 @@ +name: test +version: true diff --git a/packages/collector-extension/test/fixtures/test-at-start-path/not-docs/modules/ROOT/pages/outside-start-path.adoc b/packages/collector-extension/test/fixtures/test-at-start-path/not-docs/modules/ROOT/pages/outside-start-path.adoc new file mode 100644 index 0000000..ed20fd0 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-at-start-path/not-docs/modules/ROOT/pages/outside-start-path.adoc @@ -0,0 +1 @@ += Outside Start Path diff --git a/packages/collector-extension/test/fixtures/test-replace/.gen-replace-start-page.js b/packages/collector-extension/test/fixtures/test-replace/.gen-replace-start-page.js new file mode 100644 index 0000000..84d10de --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-replace/.gen-replace-start-page.js @@ -0,0 +1,8 @@ +'use strict' + +const { promises: fsp } = require('fs') + +;(async () => { + await fsp.mkdir('build/modules/ROOT/pages', { recursive: true }) + await fsp.writeFile('build/modules/ROOT/pages/index.adoc', '= Real Start Page\n\nThis is the real deal.\n', 'utf8') +})() diff --git a/packages/collector-extension/test/fixtures/test-replace/antora.yml b/packages/collector-extension/test/fixtures/test-replace/antora.yml new file mode 100644 index 0000000..e35bef6 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-replace/antora.yml @@ -0,0 +1,2 @@ +name: test +version: true diff --git a/packages/collector-extension/test/fixtures/test-replace/modules/ROOT/pages/index.adoc b/packages/collector-extension/test/fixtures/test-replace/modules/ROOT/pages/index.adoc new file mode 100644 index 0000000..176bd68 --- /dev/null +++ b/packages/collector-extension/test/fixtures/test-replace/modules/ROOT/pages/index.adoc @@ -0,0 +1,3 @@ += Stub Start Page + +This page is just a stub. diff --git a/packages/collector-test-harness/lib/index.js b/packages/collector-test-harness/lib/index.js index 14ae31a..ffce8c9 100644 --- a/packages/collector-test-harness/lib/index.js +++ b/packages/collector-test-harness/lib/index.js @@ -3,6 +3,83 @@ const chai = require('chai') chai.use(require('chai-fs')) +// dirty-chai must be loaded after the other plugins +// see https://github.com/prodatakey/dirty-chai#plugin-assertions chai.use(require('dirty-chai')) +const expect = chai.expect -module.exports = { expect: chai.expect } +const { configureLogger } = require('@antora/logger') +const { promises: fsp } = require('fs') +const { Git: GitServer } = require('node-git-server') +const { once } = require('events') +const yaml = require('js-yaml') + +beforeEach(() => configureLogger({ level: 'silent' })) + +async function captureStdStream (stream, fn) { + const streamWrite = stream.write + try { + const data = [] + stream.write = (buffer) => data.push(buffer) + await fn() + return data.join('') + } finally { + stream.write = streamWrite + } +} + +const captureStderr = captureStdStream.bind(null, process.stderr) + +const captureStdout = captureStdStream.bind(null, process.stdout) + +function closeServer (server) { + return once(server.close() || server, 'close') +} + +function heredoc (literals, ...values) { + const str = + literals.length > 1 + ? values.reduce((accum, value, idx) => accum + value + literals[idx + 1], literals[0]) + : literals[0] + const lines = str.trimRight().split(/^/m) + if (lines.length < 2) return str + if (lines[0] === '\n') lines.shift() + const indentRx = /^ +/ + const indentSize = Math.min(...lines.filter((l) => l.startsWith(' ')).map((l) => l.match(indentRx)[0].length)) + return (indentSize ? lines.map((l) => (l.startsWith(' ') ? l.substr(indentSize) : l)) : lines).join('') +} + +async function updateYamlFile (filepath, data) { + const parsed = yaml.load(await fsp.readFile(filepath), { schema: yaml.CORE_SCHEMA }) + Object.assign(parsed, data) + await fsp.writeFile(filepath, yaml.dump(parsed, { noArrayIndent: true }), 'utf8') +} + +function startGitServer (dir) { + return new Promise((resolve, reject) => { + const gitServer = new GitServer(dir, { autoCreate: false }) + gitServer.listen(0, { type: 'http' }, function (err) { + err ? reject(err) : resolve([gitServer, this.address().port]) + }) + }) +} + +function trapAsyncError (fn) { + return fn().then( + (retVal) => () => retVal, + (err) => () => { + throw err + } + ) +} + +module.exports = { + captureStderr, + captureStdout, + closeServer, + expect, + heredoc, + updateYamlFile, + startGitServer, + trapAsyncError, +} diff --git a/packages/collector-test-harness/package.json b/packages/collector-test-harness/package.json index 3812435..fb282ea 100644 --- a/packages/collector-test-harness/package.json +++ b/packages/collector-test-harness/package.json @@ -13,6 +13,8 @@ "devDependencies": { "chai": "~4.3", "chai-fs": "~2.0", - "dirty-chai": "~2.0" + "dirty-chai": "~2.0", + "node-git-server": "~1.0", + "@antora/logger": "~3.1" } } -- GitLab