diff --git a/.github/workflows/deploy_pr.yml b/.github/workflows/deploy_pr.yml new file mode 100644 index 00000000..35af45c1 --- /dev/null +++ b/.github/workflows/deploy_pr.yml @@ -0,0 +1,54 @@ +name: deploy_pr + +on: + pull_request: + branches: + - develop + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 19 + + - name: Install npm dependencies + run: npm ci + + - name: Run unit tests + run: npm run test:unit + + publish-gpr: + needs: test + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 19 + registry-url: https://npm.pkg.github.com/ + + - name: Install npm dependencies + run: npm ci + + - name: Build package + run: npm run build + + - name: Update package version + run: | + SHORT_SHA=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}") + CURRENT_PACKAGE_VERSION=$(cat package.json | jq -r '.version') + npm version "${CURRENT_PACKAGE_VERSION}-pr${{ github.event.number }}.${SHORT_SHA}" --no-git-tag-version + + - name: Publish package + run: | + echo "$(jq '.publishConfig.registry = "https://npm.pkg.github.com"' package.json)" > package.json + echo "$( jq '.name = "@IQSS/dataverse-client-javascript"' package.json )" > package.json + npm publish --@IQSS:registry=https://npm.pkg.github.com + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index f5e007ff..0ade550a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ A JavaScript/TypeScript API wrapper for [Dataverse](http://guides.dataverse.org/ ## NPM -Module available as `js-dataverse` at https://www.npmjs.com/package/js-dataverse +A stable 1.x version of this package is available as `js-dataverse` at https://www.npmjs.com/package/js-dataverse + +An unstable 2.x version of this package with breaking changes is under development. Until a 2.0 version is officially released, it can be installed from https://github.com/IQSS/dataverse-client-javascript/pkgs/npm/dataverse-client-javascript ## Getting Started diff --git a/jest.config.js b/jest.config.js index 95fe9340..cbd89f75 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,5 +5,5 @@ module.exports = { }, testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.ts$', moduleFileExtensions: ['ts', 'js', 'json', 'node'], - coveragePathIgnorePatterns: ['testHelpers'], + coveragePathIgnorePatterns: ['node_modules', 'testHelpers'], }; diff --git a/package-lock.json b/package-lock.json index 8836e639..ca858690 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "license": "MIT", "dependencies": { "@types/node": "^18.15.11", + "@types/turndown": "5.0.1", "axios": "^1.3.4", + "turndown": "^7.1.2", "typescript": "^4.9.5" }, "devDependencies": { @@ -29,12 +31,12 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -54,30 +56,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", + "version": "7.21.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.7.tgz", + "integrity": "sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", + "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", + "@babel/generator": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helpers": "^7.21.5", + "@babel/parser": "^7.21.8", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -108,12 +110,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz", + "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -122,27 +124,13 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", + "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.21.4", + "@babel/compat-data": "^7.21.5", "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", @@ -180,9 +168,9 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", + "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -226,40 +214,40 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", + "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-simple-access": "^7.21.5", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", + "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", + "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -278,9 +266,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", + "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -305,14 +293,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", + "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -395,9 +383,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", + "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -598,19 +586,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", + "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", + "@babel/generator": "^7.21.5", + "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/parser": "^7.21.5", + "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -628,12 +616,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", + "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, @@ -647,15 +635,39 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -671,9 +683,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", + "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1099,13 +1111,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -1130,21 +1143,27 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1187,21 +1206,21 @@ "dev": true }, "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.1.0.tgz", + "integrity": "sha512-w1qd368vtrwttm1PRJWPW1QHlbmHrVDGs1eBH/jZvRPUFS4MNXV9Q33EQdjOdeAxZ7O8+3wM7zxztm2nfUSyKw==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { @@ -1215,6 +1234,15 @@ "type-detect": "^4.0.8" } }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/@sinonjs/text-encoding": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", @@ -1254,18 +1282,18 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.5.tgz", + "integrity": "sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" } }, "node_modules/@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, "node_modules/@types/graceful-fs": { @@ -1302,9 +1330,9 @@ } }, "node_modules/@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -1329,15 +1357,15 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.13.tgz", - "integrity": "sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ==", + "version": "10.0.15", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", + "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -1355,6 +1383,11 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/turndown": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz", + "integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==" + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -1371,19 +1404,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.5.tgz", + "integrity": "sha512-feA9xbVRWJZor+AnLNAr7A8JRWeZqHUf4T9tlP+TN04b05pFVhO5eN7/O93Y/1OUlLMHKbnJisgDURs/qvtqdg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/type-utils": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -1405,14 +1438,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", - "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.5.tgz", + "integrity": "sha512-NJXQC4MRnF9N9yWqQE2/KLRSOLvrrlZb48NGVfBa+RuPMN6B7ZcK5jZOvhuygv4D64fRKnZI4L4p8+M+rfeQuw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.52.0", - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "debug": "^4.3.4" }, "engines": { @@ -1431,88 +1464,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", - "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", - "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", - "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.52.0", - "@typescript-eslint/visitor-keys": "5.52.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.52.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", - "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.52.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.5.tgz", + "integrity": "sha512-jVecWwnkX6ZgutF+DovbBJirZcAxgxC0EOHYt/niMROf8p4PwxxG32Qdhj/iIQQIuOflLjNkxoXyArkcIP7C3A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1523,13 +1482,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.5.tgz", + "integrity": "sha512-4eyhS7oGym67/pSxA2mmNq7X164oqDYNnZCUayBwJZIRVvKpBCMBzFnFxjeoDeShjtO6RQBHBuwybuX3POnDqg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@typescript-eslint/typescript-estree": "5.59.5", + "@typescript-eslint/utils": "5.59.5", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1550,9 +1509,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.5.tgz", + "integrity": "sha512-xkfRPHbqSH4Ggx4eHRIO/eGL8XL4Ysb4woL8c87YuAo8Md7AUjyWKa9YMwTL519SyDPrfEgKdewjkxNCVeJW7w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1563,13 +1522,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.5.tgz", + "integrity": "sha512-+XXdLN2CZLZcD/mO7mQtJMvCkzRfmODbeSKuMY/yXbGkzvA9rJyDY5qDYNoiz2kP/dmyAxXquL2BvLQLJFPQIg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/visitor-keys": "5.59.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1590,18 +1549,18 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.5.tgz", + "integrity": "sha512-sCEHOiw+RbyTii9c3/qN74hYDPNORb8yWCoPLmB7BIflhplJ65u2PBpdRla12e3SSTJ2erRkPjz7ngLHhUegxA==", "dev": true, "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.59.5", + "@typescript-eslint/types": "5.59.5", + "@typescript-eslint/typescript-estree": "5.59.5", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -1616,12 +1575,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "version": "5.59.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.5.tgz", + "integrity": "sha512-qL+Oz+dbeBRTeyJTIy0eniD3uvqU7x+y1QceBismZ41hd4aBSRh8UAw4pZP0+XzLuPZmx4raNMq/I+59W2lXKA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/types": "5.59.5", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1965,9 +1924,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001473", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz", - "integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", + "version": "1.0.30001487", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz", + "integrity": "sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA==", "dev": true, "funding": [ { @@ -2209,6 +2168,15 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", @@ -2242,10 +2210,15 @@ "node": ">=6.0.0" } }, + "node_modules/domino": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==" + }, "node_modules/electron-to-chromium": { - "version": "1.4.348", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.348.tgz", - "integrity": "sha512-gM7TdwuG3amns/1rlgxMbeeyNoBFPa+4Uu0c7FeROWh4qWmvSOnvcslKmWy51ggLKZ2n/F/4i2HJ+PVNxH9uCQ==", + "version": "1.4.394", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.394.tgz", + "integrity": "sha512-0IbC2cfr8w5LxTz+nmn2cJTGafsK9iauV2r5A5scfzyovqLrxuLoxOHE5OBobP3oVIggJT+0JfKnw9sm87c8Hw==", "dev": true }, "node_modules/emittery": { @@ -2294,13 +2267,15 @@ } }, "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "version": "8.40.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", + "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.40.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -2310,10 +2285,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2335,7 +2309,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -2387,37 +2360,10 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2439,9 +2385,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2449,6 +2395,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -2473,14 +2422,14 @@ } }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3018,9 +2967,9 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -3186,15 +3135,15 @@ } }, "node_modules/jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", - "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "dependencies": { - "@jest/core": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^29.4.3" + "jest-cli": "^29.5.0" }, "bin": { "jest": "bin/jest.js" @@ -4048,6 +3997,15 @@ "path-to-regexp": "^1.7.0" } }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -4352,9 +4310,9 @@ } }, "node_modules/prettier": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", - "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -4420,9 +4378,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", "dev": true, "funding": [ { @@ -4461,18 +4419,6 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4483,12 +4429,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4587,9 +4533,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -4629,9 +4575,9 @@ "dev": true }, "node_modules/sinon": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.3.tgz", - "integrity": "sha512-si3geiRkeovP7Iel2O+qGL4NrO9vbMf3KsrJEi0ghP1l5aBkB5UxARea5j0FUsSqH3HLBh0dQPAyQ8fObRUqHw==", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.4.tgz", + "integrity": "sha512-uzmfN6zx3GQaria1kwgWGeKiXSSbShBbue6Dcj0SI8fiCNFbiUDqKl57WFlY5lyhxZVUKmXvzgG2pilRQCBwWg==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -4646,24 +4592,6 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -4866,9 +4794,9 @@ } }, "node_modules/ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -4891,7 +4819,7 @@ "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", - "typescript": ">=4.3" + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { @@ -4929,6 +4857,14 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/turndown": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz", + "integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==", + "dependencies": { + "domino": "^2.1.6" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4975,9 +4911,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -4987,6 +4923,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -4994,7 +4934,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -5114,9 +5054,9 @@ "dev": true }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", diff --git a/package.json b/package.json index cdd257d6..8e28323a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ ], "scripts": { "build": "tsc", - "publish": "tsc && npm publish", "test": "jest -c jest.config.js", "test:unit": "jest -c jest.config.unit.js", "test:integration": "jest -c jest.config.integration.js", @@ -47,7 +46,9 @@ }, "dependencies": { "@types/node": "^18.15.11", + "@types/turndown": "^5.0.1", "axios": "^1.3.4", - "typescript": "^4.9.5" + "typescript": "^4.9.5", + "turndown": "^7.1.2" } } diff --git a/src/datasets/domain/models/Dataset.ts b/src/datasets/domain/models/Dataset.ts new file mode 100644 index 00000000..046f4022 --- /dev/null +++ b/src/datasets/domain/models/Dataset.ts @@ -0,0 +1,41 @@ +export interface Dataset { + id: number; + persistentId: string; + versionId: number; + versionInfo: DatasetVersionInfo; + license?: DatasetLicense; + metadataBlocks: DatasetMetadataBlock[]; +} + +export interface DatasetVersionInfo { + majorNumber: number; + minorNumber: number; + state: DatasetVersionState; + createTime: Date; + lastUpdateTime: Date; + releaseTime?: Date; +} + +export enum DatasetVersionState { + DRAFT = 'DRAFT', + RELEASED = 'RELEASED', + ARCHIVED = 'ARCHIVED', + DEACCESSIONED = 'DEACCESSIONED', +} + +export interface DatasetLicense { + name: string; + uri: string; + iconUri?: string; +} + +export interface DatasetMetadataBlock { + name: string; + fields: DatasetMetadataFields; +} + +export type DatasetMetadataFields = Record; + +export type DatasetMetadataFieldValue = string | string[] | DatasetMetadataSubField | DatasetMetadataSubField[]; + +export type DatasetMetadataSubField = Record; diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts new file mode 100644 index 00000000..59aae717 --- /dev/null +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -0,0 +1,10 @@ +import { Dataset } from '../models/Dataset'; + +export interface IDatasetsRepository { + getDatasetSummaryFieldNames(): Promise; + getDatasetById(datasetId: number, datasetVersionId?: string): Promise; + getDatasetByPersistentId(datasetPersistentId: string, datasetVersionId?: string): Promise; + getPrivateUrlDataset(token: string): Promise; + getDatasetCitation(datasetId: number, datasetVersionId?: string): Promise; + getPrivateUrlDatasetCitation(token: string): Promise; +} diff --git a/src/datasets/domain/useCases/GetDatasetById.ts b/src/datasets/domain/useCases/GetDatasetById.ts new file mode 100644 index 00000000..15e14748 --- /dev/null +++ b/src/datasets/domain/useCases/GetDatasetById.ts @@ -0,0 +1,15 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; +import { Dataset } from '../models/Dataset'; + +export class GetDatasetById implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(datasetId: number, datasetVersionId?: string): Promise { + return await this.datasetsRepository.getDatasetById(datasetId, datasetVersionId); + } +} diff --git a/src/datasets/domain/useCases/GetDatasetByPersistentId.ts b/src/datasets/domain/useCases/GetDatasetByPersistentId.ts new file mode 100644 index 00000000..66a39a3b --- /dev/null +++ b/src/datasets/domain/useCases/GetDatasetByPersistentId.ts @@ -0,0 +1,15 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; +import { Dataset } from '../models/Dataset'; + +export class GetDatasetByPersistentId implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(datasetPersistentId: string, datasetVersionId?: string): Promise { + return await this.datasetsRepository.getDatasetByPersistentId(datasetPersistentId, datasetVersionId); + } +} diff --git a/src/datasets/domain/useCases/GetDatasetCitation.ts b/src/datasets/domain/useCases/GetDatasetCitation.ts new file mode 100644 index 00000000..ac418df3 --- /dev/null +++ b/src/datasets/domain/useCases/GetDatasetCitation.ts @@ -0,0 +1,14 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; + +export class GetDatasetCitation implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(datasetId: number, datasetVersionId?: string): Promise { + return await this.datasetsRepository.getDatasetCitation(datasetId, datasetVersionId); + } +} diff --git a/src/datasets/domain/useCases/GetDatasetSummaryFieldNames.ts b/src/datasets/domain/useCases/GetDatasetSummaryFieldNames.ts new file mode 100644 index 00000000..4041e408 --- /dev/null +++ b/src/datasets/domain/useCases/GetDatasetSummaryFieldNames.ts @@ -0,0 +1,14 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; + +export class GetDatasetSummaryFieldNames implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(): Promise { + return await this.datasetsRepository.getDatasetSummaryFieldNames(); + } +} diff --git a/src/datasets/domain/useCases/GetPrivateUrlDataset.ts b/src/datasets/domain/useCases/GetPrivateUrlDataset.ts new file mode 100644 index 00000000..3580632c --- /dev/null +++ b/src/datasets/domain/useCases/GetPrivateUrlDataset.ts @@ -0,0 +1,15 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; +import { Dataset } from '../models/Dataset'; + +export class GetPrivateUrlDataset implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(token: string): Promise { + return await this.datasetsRepository.getPrivateUrlDataset(token); + } +} diff --git a/src/datasets/domain/useCases/GetPrivateUrlDatasetCitation.ts b/src/datasets/domain/useCases/GetPrivateUrlDatasetCitation.ts new file mode 100644 index 00000000..7ff06f47 --- /dev/null +++ b/src/datasets/domain/useCases/GetPrivateUrlDatasetCitation.ts @@ -0,0 +1,14 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase'; +import { IDatasetsRepository } from '../repositories/IDatasetsRepository'; + +export class GetPrivateUrlDatasetCitation implements UseCase { + private datasetsRepository: IDatasetsRepository; + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository; + } + + async execute(token: string): Promise { + return await this.datasetsRepository.getPrivateUrlDatasetCitation(token); + } +} diff --git a/src/datasets/index.ts b/src/datasets/index.ts new file mode 100644 index 00000000..64c39963 --- /dev/null +++ b/src/datasets/index.ts @@ -0,0 +1,35 @@ +import { DatasetsRepository } from './infra/repositories/DatasetsRepository'; +import { GetDatasetSummaryFieldNames } from './domain/useCases/GetDatasetSummaryFieldNames'; +import { GetDatasetById } from './domain/useCases/GetDatasetById'; +import { GetDatasetByPersistentId } from './domain/useCases/GetDatasetByPersistentId'; +import { GetPrivateUrlDataset } from './domain/useCases/GetPrivateUrlDataset'; +import { GetDatasetCitation } from './domain/useCases/GetDatasetCitation'; +import { GetPrivateUrlDatasetCitation } from './domain/useCases/GetPrivateUrlDatasetCitation'; + +const datasetsRepository = new DatasetsRepository(); + +const getDatasetSummaryFieldNames = new GetDatasetSummaryFieldNames(datasetsRepository); +const getDatasetById = new GetDatasetById(datasetsRepository); +const getDatasetByPersistentId = new GetDatasetByPersistentId(datasetsRepository); +const getPrivateUrlDataset = new GetPrivateUrlDataset(datasetsRepository); +const getDatasetCitation = new GetDatasetCitation(datasetsRepository); +const getPrivateUrlDatasetCitation = new GetPrivateUrlDatasetCitation(datasetsRepository); + +export { + getDatasetSummaryFieldNames, + getDatasetById, + getDatasetByPersistentId, + getPrivateUrlDataset, + getDatasetCitation, + getPrivateUrlDatasetCitation, +}; +export { + Dataset, + DatasetVersionInfo, + DatasetVersionState, + DatasetLicense, + DatasetMetadataBlock, + DatasetMetadataFields, + DatasetMetadataFieldValue, + DatasetMetadataSubField, +} from './domain/models/Dataset'; diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts new file mode 100644 index 00000000..56328fcb --- /dev/null +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -0,0 +1,67 @@ +import { ApiRepository } from '../../../core/infra/repositories/ApiRepository'; +import { IDatasetsRepository } from '../../domain/repositories/IDatasetsRepository'; +import { Dataset } from '../../domain/models/Dataset'; +import { transformVersionResponseToDataset } from './transformers/datasetTransformers'; + +export class DatasetsRepository extends ApiRepository implements IDatasetsRepository { + DATASET_VERSION_LATEST = ':latest'; + + public async getDatasetSummaryFieldNames(): Promise { + return this.doGet('/datasets/summaryFieldNames') + .then((response) => response.data.data) + .catch((error) => { + throw error; + }); + } + + public async getPrivateUrlDataset(token: string): Promise { + return this.doGet(`/datasets/privateUrlDatasetVersion/${token}`) + .then((response) => transformVersionResponseToDataset(response)) + .catch((error) => { + throw error; + }); + } + + public async getDatasetById(datasetId: number, datasetVersionId?: string): Promise { + if (datasetVersionId === undefined) { + datasetVersionId = this.DATASET_VERSION_LATEST; + } + return this.getDatasetVersion(`/datasets/${datasetId}/versions/${datasetVersionId}`); + } + + public async getDatasetByPersistentId(datasetPersistentId: string, datasetVersionId?: string): Promise { + if (datasetVersionId === undefined) { + datasetVersionId = this.DATASET_VERSION_LATEST; + } + return this.getDatasetVersion( + `/datasets/:persistentId/versions/${datasetVersionId}?persistentId=${datasetPersistentId}`, + ); + } + + public async getDatasetCitation(datasetId: number, datasetVersionId?: string): Promise { + if (datasetVersionId === undefined) { + datasetVersionId = this.DATASET_VERSION_LATEST; + } + return this.doGet(`/datasets/${datasetId}/versions/${datasetVersionId}/citation`, true) + .then((response) => response.data.data.message) + .catch((error) => { + throw error; + }); + } + + private async getDatasetVersion(endpoint: string): Promise { + return this.doGet(endpoint, true) + .then((response) => transformVersionResponseToDataset(response)) + .catch((error) => { + throw error; + }); + } + + public async getPrivateUrlDatasetCitation(token: string): Promise { + return this.doGet(`/datasets/privateUrlDatasetVersion/${token}/citation`) + .then((response) => response.data.data.message) + .catch((error) => { + throw error; + }); + } +} diff --git a/src/datasets/infra/repositories/transformers/datasetTransformers.ts b/src/datasets/infra/repositories/transformers/datasetTransformers.ts new file mode 100644 index 00000000..a678ca70 --- /dev/null +++ b/src/datasets/infra/repositories/transformers/datasetTransformers.ts @@ -0,0 +1,98 @@ +import { + Dataset, + DatasetVersionState, + DatasetMetadataFields, + DatasetMetadataBlock, + DatasetMetadataSubField, + DatasetMetadataFieldValue, + DatasetLicense, +} from '../../../domain/models/Dataset'; +import { AxiosResponse } from 'axios'; +import TurndownService from 'turndown'; + +const turndownService = new TurndownService(); + +export const transformVersionResponseToDataset = (response: AxiosResponse): Dataset => { + const versionPayload = response.data.data; + return transformVersionPayloadToDataset(versionPayload); +}; + +const transformVersionPayloadToDataset = (versionPayload: any): Dataset => { + let datasetModel: Dataset = { + id: versionPayload.datasetId, + persistentId: versionPayload.datasetPersistentId, + versionId: versionPayload.id, + versionInfo: { + majorNumber: versionPayload.versionNumber, + minorNumber: versionPayload.versionMinorNumber, + state: versionPayload.versionState as DatasetVersionState, + createTime: new Date(versionPayload.createTime), + lastUpdateTime: new Date(versionPayload.lastUpdateTime), + releaseTime: new Date(versionPayload.releaseTime), + }, + metadataBlocks: transformPayloadToDatasetMetadataBlocks(versionPayload.metadataBlocks), + }; + if (versionPayload.hasOwnProperty('license')) { + datasetModel.license = transformPayloadToDatasetLicense(versionPayload.license); + } + return datasetModel; +}; + +const transformPayloadToDatasetLicense = (licensePayload: any): DatasetLicense => { + let datasetLicense: DatasetLicense = { + name: licensePayload.name, + uri: licensePayload.uri, + }; + if (licensePayload.hasOwnProperty('iconUri')) { + datasetLicense.iconUri = licensePayload.iconUri; + } + return datasetLicense; +}; + +const transformPayloadToDatasetMetadataBlocks = (metadataBlocksPayload: any): DatasetMetadataBlock[] => { + return Object.keys(metadataBlocksPayload).map((metadataBlockKey) => { + return { + name: metadataBlockKey, + fields: transformPayloadToDatasetMetadataFields(metadataBlocksPayload[metadataBlockKey].fields), + }; + }); +}; + +const transformPayloadToDatasetMetadataFields = (metadataFieldsPayload: any): DatasetMetadataFields => { + const metadataFieldKeys = Object.keys(metadataFieldsPayload); + const metadataFields: DatasetMetadataFields = {}; + for (let metadataFieldKey of metadataFieldKeys) { + const metadataField = metadataFieldsPayload[metadataFieldKey]; + const metadataFieldTypeName = metadataField.typeName; + metadataFields[metadataFieldTypeName] = transformPayloadToDatasetMetadataFieldValue(metadataField.value); + } + return metadataFields; +}; + +const transformPayloadToDatasetMetadataFieldValue = (metadataFieldValuePayload: any): DatasetMetadataFieldValue => { + let metadataFieldValue: DatasetMetadataFieldValue; + if (Array.isArray(metadataFieldValuePayload)) { + const isArrayOfObjects = typeof metadataFieldValuePayload[0] === 'object'; + if (!isArrayOfObjects) { + metadataFieldValue = metadataFieldValuePayload.map(transformHtmlToMarkdown); + } else { + const datasetMetadataSubfields: DatasetMetadataSubField[] = []; + metadataFieldValuePayload.forEach(function (metadataSubFieldValuePayload) { + const subFieldKeys = Object.keys(metadataSubFieldValuePayload); + const record: DatasetMetadataSubField = {}; + for (let subFieldKey of subFieldKeys) { + record[subFieldKey] = transformHtmlToMarkdown(metadataSubFieldValuePayload[subFieldKey].value); + } + datasetMetadataSubfields.push(record); + }); + metadataFieldValue = datasetMetadataSubfields; + } + } else { + metadataFieldValue = transformHtmlToMarkdown(metadataFieldValuePayload); + } + return metadataFieldValue; +}; + +const transformHtmlToMarkdown = (source: string): string => { + return turndownService.turndown(source); +}; diff --git a/src/index.ts b/src/index.ts index b04f0a42..ada6375d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,3 +2,4 @@ export * from './core'; export * from './info'; export * from './users'; export * from './auth'; +export * from './datasets'; diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts new file mode 100644 index 00000000..4d5e5c34 --- /dev/null +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -0,0 +1,16 @@ +import { ApiConfig } from '../../../src/core/infra/repositories/ApiConfig'; + +describe('getDatasetSummaryFieldNames', () => { + // TODO: Change API URL to another of an integration test oriented Dataverse instance + ApiConfig.init('https://demo.dataverse.org/api/v1'); + + test('should return dataset field names', async () => { + // TODO + }); +}); + +// TODO: getDataset tests + +// TODO: getPrivateUrlDataset tests + +// TODO: getDatasetCitation tests diff --git a/test/testHelpers/datasets/datasetHelper.ts b/test/testHelpers/datasets/datasetHelper.ts new file mode 100644 index 00000000..c5116f04 --- /dev/null +++ b/test/testHelpers/datasets/datasetHelper.ts @@ -0,0 +1,159 @@ +import { Dataset, DatasetVersionState, DatasetLicense } from '../../../src/datasets/domain/models/Dataset'; +import TurndownService from 'turndown'; + +const turndownService = new TurndownService(); + +const DATASET_CREATE_TIME_STR = '2023-05-15T08:21:01Z'; +const DATASET_UPDATE_TIME_STR = '2023-05-15T08:21:03Z'; +const DATASET_RELEASE_TIME_STR = '2023-05-15T08:21:03Z'; + +const DATASET_HTML_DESCRIPTION = + '

Title 1

Test paragraph 1

Test paragraph 2

Hello world

Title 2

Title 3

'; + +export const createDatasetModel = (license?: DatasetLicense): Dataset => { + let datasetModel: Dataset = { + id: 1, + persistentId: 'doi:10.5072/FK2/HC6KTB', + versionId: 19, + versionInfo: { + majorNumber: 1, + minorNumber: 0, + state: DatasetVersionState.RELEASED, + createTime: new Date(DATASET_CREATE_TIME_STR), + lastUpdateTime: new Date(DATASET_UPDATE_TIME_STR), + releaseTime: new Date(DATASET_RELEASE_TIME_STR), + }, + metadataBlocks: [ + { + name: 'citation', + fields: { + title: 'test', + author: [ + { + authorName: 'Admin, Dataverse', + authorAffiliation: 'Dataverse.org', + }, + { + authorName: 'Owner, Dataverse', + authorAffiliation: 'Dataverse.org', + }, + ], + subject: ['Subject1', 'Subject2'], + dsDescription: [ + { + dsDescriptionValue: turndownService.turndown(DATASET_HTML_DESCRIPTION), + }, + ], + }, + }, + ], + }; + if (license !== undefined) { + datasetModel.license = license; + } + return datasetModel; +}; + +export const createDatasetVersionPayload = (license?: DatasetLicense): any => { + let datasetPayload: any = { + id: 19, + datasetId: 1, + datasetPersistentId: 'doi:10.5072/FK2/HC6KTB', + versionNumber: 1, + versionMinorNumber: 0, + versionState: 'RELEASED', + lastUpdateTime: DATASET_UPDATE_TIME_STR, + releaseTime: DATASET_RELEASE_TIME_STR, + createTime: DATASET_CREATE_TIME_STR, + license: { + name: 'CC0 1.0', + uri: 'https://creativecommons.org/publicdomain/zero/1.0/', + iconUri: 'https://licensebuttons.net/p/zero/1.0/88x31.png', + }, + metadataBlocks: { + citation: { + name: 'citation', + fields: [ + { + typeName: 'title', + multiple: false, + typeClass: 'primitive', + value: 'test', + }, + { + typeName: 'author', + multiple: true, + typeClass: 'compound', + value: [ + { + authorName: { + typeName: 'authorName', + multiple: false, + typeClass: 'primitive', + value: 'Admin, Dataverse', + }, + authorAffiliation: { + typeName: 'authorAffiliation', + multiple: false, + typeClass: 'primitive', + value: 'Dataverse.org', + }, + }, + { + authorName: { + typeName: 'authorName', + multiple: false, + typeClass: 'primitive', + value: 'Owner, Dataverse', + }, + authorAffiliation: { + typeName: 'authorAffiliation', + multiple: false, + typeClass: 'primitive', + value: 'Dataverse.org', + }, + }, + ], + }, + { + typeName: 'subject', + multiple: true, + typeClass: 'controlledVocabulary', + value: ['Subject1', 'Subject2'], + }, + { + typeName: 'dsDescription', + multiple: true, + typeClass: 'compound', + value: [ + { + dsDescriptionValue: { + typeName: 'dsDescriptionValue', + multiple: false, + typeClass: 'primitive', + value: DATASET_HTML_DESCRIPTION, + }, + }, + ], + }, + ], + }, + }, + files: [], + }; + if (license !== undefined) { + datasetPayload.license = license; + } + return datasetPayload; +}; + +export const createDatasetLicenseModel = (withIconUri: boolean = true): DatasetLicense => { + let datasetLicense: DatasetLicense = { + name: 'CC0 1.0', + uri: 'https://creativecommons.org/publicdomain/zero/1.0/', + }; + if (withIconUri) { + datasetLicense.iconUri = 'https://licensebuttons.net/p/zero/1.0/88x31.png'; + } + return datasetLicense; +}; diff --git a/test/unit/datasets/DatasetsRepository.test.ts b/test/unit/datasets/DatasetsRepository.test.ts new file mode 100644 index 00000000..8100bd66 --- /dev/null +++ b/test/unit/datasets/DatasetsRepository.test.ts @@ -0,0 +1,306 @@ +import { DatasetsRepository } from '../../../src/datasets/infra/repositories/DatasetsRepository'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; +import axios from 'axios'; +import { expect } from 'chai'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; +import { ApiConfig } from '../../../src/core/infra/repositories/ApiConfig'; +import { + createDatasetModel, + createDatasetVersionPayload, + createDatasetLicenseModel, +} from '../../testHelpers/datasets/datasetHelper'; + +describe('DatasetsRepository', () => { + const sandbox: SinonSandbox = createSandbox(); + const sut: DatasetsRepository = new DatasetsRepository(); + const testDatasetVersionSuccessfulResponse = { + data: { + status: 'OK', + data: createDatasetVersionPayload(), + }, + }; + const testCitation = 'test citation'; + const testCitationSuccessfulResponse = { + data: { + status: 'OK', + data: { + message: testCitation, + }, + }, + }; + const testErrorResponse = { + response: { + status: 'ERROR', + message: 'test', + }, + }; + const testPrivateUrlToken = 'testToken'; + const testDatasetModel = createDatasetModel(); + const testApiUrl = 'https://test.dataverse.org/api/v1'; + + ApiConfig.init(testApiUrl); + + afterEach(() => { + sandbox.restore(); + }); + + describe('getDatasetSummaryFieldNames', () => { + test('should return fields on successful response', async () => { + const testFieldNames = ['test1', 'test2']; + const testSuccessfulResponse = { + data: { + status: 'OK', + data: testFieldNames, + }, + }; + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testSuccessfulResponse); + + const actual = await sut.getDatasetSummaryFieldNames(); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/summaryFieldNames`, { withCredentials: false }); + assert.match(actual, testFieldNames); + }); + + test('should return error result on error response', async () => { + const testErrorResponse = { + response: { + status: 'ERROR', + message: 'test', + }, + }; + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getDatasetSummaryFieldNames().catch((e) => (error = e)); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/summaryFieldNames`, { withCredentials: false }); + expect(error).to.be.instanceOf(Error); + }); + }); + + describe('getDatasetById', () => { + test('should return Dataset when providing id, no version, and response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionSuccessfulResponse); + + const actual = await sut.getDatasetById(testDatasetModel.id); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/${testDatasetModel.id}/versions/:latest`, { + withCredentials: true, + }); + assert.match(actual, testDatasetModel); + }); + + test('should return Dataset when providing id, version, and response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionSuccessfulResponse); + + const actual = await sut.getDatasetById(testDatasetModel.id, String(testDatasetModel.versionId)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/${testDatasetModel.id}/versions/${testDatasetModel.versionId}`, + { + withCredentials: true, + }, + ); + assert.match(actual, testDatasetModel); + }); + + test('should return Dataset when providing id, version, and response with license is successful', async () => { + const testDatasetLicense = createDatasetLicenseModel(); + const testDatasetVersionWithLicenseSuccessfulResponse = { + data: { + status: 'OK', + data: createDatasetVersionPayload(testDatasetLicense), + }, + }; + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionWithLicenseSuccessfulResponse); + + const actual = await sut.getDatasetById(testDatasetModel.id, String(testDatasetModel.versionId)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/${testDatasetModel.id}/versions/${testDatasetModel.versionId}`, + { + withCredentials: true, + }, + ); + assert.match(actual, createDatasetModel(testDatasetLicense)); + }); + + test('should return Dataset when providing id, version, and response with license without icon URI is successful', async () => { + const testDatasetLicenseWithoutIconUri = createDatasetLicenseModel(false); + const testDatasetVersionWithLicenseSuccessfulResponse = { + data: { + status: 'OK', + data: createDatasetVersionPayload(testDatasetLicenseWithoutIconUri), + }, + }; + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionWithLicenseSuccessfulResponse); + + const actual = await sut.getDatasetById(testDatasetModel.id, String(testDatasetModel.versionId)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/${testDatasetModel.id}/versions/${testDatasetModel.versionId}`, + { + withCredentials: true, + }, + ); + assert.match(actual, createDatasetModel(testDatasetLicenseWithoutIconUri)); + }); + + test('should return error on repository read error', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getDatasetById(testDatasetModel.id).catch((e) => (error = e)); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/${testDatasetModel.id}/versions/:latest`, { + withCredentials: true, + }); + expect(error).to.be.instanceOf(Error); + }); + }); + + describe('getDatasetByPersistentId', () => { + test('should return Dataset when providing persistent id, no version, and response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionSuccessfulResponse); + + const actual = await sut.getDatasetByPersistentId(testDatasetModel.persistentId); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/:persistentId/versions/:latest?persistentId=${testDatasetModel.persistentId}`, + { + withCredentials: true, + }, + ); + assert.match(actual, testDatasetModel); + }); + + test('should return Dataset when providing persistent id, version, and response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionSuccessfulResponse); + + const actual = await sut.getDatasetByPersistentId( + testDatasetModel.persistentId, + String(testDatasetModel.versionId), + ); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/:persistentId/versions/${testDatasetModel.versionId}?persistentId=${testDatasetModel.persistentId}`, + { + withCredentials: true, + }, + ); + assert.match(actual, testDatasetModel); + }); + + test('should return error on repository read error', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getDatasetByPersistentId(testDatasetModel.persistentId).catch((e) => (error = e)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/:persistentId/versions/:latest?persistentId=${testDatasetModel.persistentId}`, + { + withCredentials: true, + }, + ); + expect(error).to.be.instanceOf(Error); + }); + }); + + describe('getPrivateUrlDataset', () => { + test('should return Dataset when response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testDatasetVersionSuccessfulResponse); + + const actual = await sut.getPrivateUrlDataset(testPrivateUrlToken); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/privateUrlDatasetVersion/${testPrivateUrlToken}`, { + withCredentials: false, + }); + assert.match(actual, testDatasetModel); + }); + + test('should return error on repository read error', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getPrivateUrlDataset(testPrivateUrlToken).catch((e) => (error = e)); + + assert.calledWithExactly(axiosGetStub, `${testApiUrl}/datasets/privateUrlDatasetVersion/${testPrivateUrlToken}`, { + withCredentials: false, + }); + expect(error).to.be.instanceOf(Error); + }); + }); + + describe('getDatasetCitation', () => { + test('should return citation when response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testCitationSuccessfulResponse); + + const actual = await sut.getDatasetCitation(testDatasetModel.id, undefined); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/${testDatasetModel.id}/versions/:latest/citation`, + { + withCredentials: true, + }, + ); + assert.match(actual, testCitation); + }); + + test('should return error on repository read error', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getDatasetCitation(1, undefined).catch((e) => (error = e)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/${testDatasetModel.id}/versions/:latest/citation`, + { + withCredentials: true, + }, + ); + expect(error).to.be.instanceOf(Error); + }); + }); + + describe('getPrivateUrlDatasetCitation', () => { + test('should return citation when response is successful', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').resolves(testCitationSuccessfulResponse); + + const actual = await sut.getPrivateUrlDatasetCitation(testPrivateUrlToken); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/privateUrlDatasetVersion/${testPrivateUrlToken}/citation`, + { + withCredentials: false, + }, + ); + assert.match(actual, testCitation); + }); + + test('should return error on repository read error', async () => { + const axiosGetStub = sandbox.stub(axios, 'get').rejects(testErrorResponse); + + let error: ReadError = undefined; + await sut.getPrivateUrlDatasetCitation(testPrivateUrlToken).catch((e) => (error = e)); + + assert.calledWithExactly( + axiosGetStub, + `${testApiUrl}/datasets/privateUrlDatasetVersion/${testPrivateUrlToken}/citation`, + { + withCredentials: false, + }, + ); + expect(error).to.be.instanceOf(Error); + }); + }); +}); diff --git a/test/unit/datasets/GetDatasetById.test.ts b/test/unit/datasets/GetDatasetById.test.ts new file mode 100644 index 00000000..07199b37 --- /dev/null +++ b/test/unit/datasets/GetDatasetById.test.ts @@ -0,0 +1,38 @@ +import { GetDatasetById } from '../../../src/datasets/domain/useCases/GetDatasetById'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; +import { createDatasetModel } from '../../testHelpers/datasets/datasetHelper'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + + afterEach(() => { + sandbox.restore(); + }); + + test('should return dataset on repository success', async () => { + const testDataset = createDatasetModel(); + const datasetsRepositoryStub = {}; + const getDatasetStub = sandbox.stub().returns(testDataset); + datasetsRepositoryStub.getDatasetById = getDatasetStub; + const sut = new GetDatasetById(datasetsRepositoryStub); + + const actual = await sut.execute(1); + + assert.match(actual, testDataset); + assert.calledWithExactly(getDatasetStub, 1, undefined); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getDatasetById = sandbox.stub().throwsException(testReadError); + const sut = new GetDatasetById(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute(1).catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +}); diff --git a/test/unit/datasets/GetDatasetByPersistentId.test.ts b/test/unit/datasets/GetDatasetByPersistentId.test.ts new file mode 100644 index 00000000..b3ba5060 --- /dev/null +++ b/test/unit/datasets/GetDatasetByPersistentId.test.ts @@ -0,0 +1,38 @@ +import { GetDatasetByPersistentId } from '../../../src/datasets/domain/useCases/GetDatasetByPersistentId'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; +import { createDatasetModel } from '../../testHelpers/datasets/datasetHelper'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + + afterEach(() => { + sandbox.restore(); + }); + + test('should return dataset on repository success', async () => { + const testDataset = createDatasetModel(); + const datasetsRepositoryStub = {}; + const getDatasetStub = sandbox.stub().returns(testDataset); + datasetsRepositoryStub.getDatasetByPersistentId = getDatasetStub; + const sut = new GetDatasetByPersistentId(datasetsRepositoryStub); + + const actual = await sut.execute('1'); + + assert.match(actual, testDataset); + assert.calledWithExactly(getDatasetStub, '1', undefined); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getDatasetByPersistentId = sandbox.stub().throwsException(testReadError); + const sut = new GetDatasetByPersistentId(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute('1').catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +}); diff --git a/test/unit/datasets/GetDatasetCitation.test.ts b/test/unit/datasets/GetDatasetCitation.test.ts new file mode 100644 index 00000000..141fb3af --- /dev/null +++ b/test/unit/datasets/GetDatasetCitation.test.ts @@ -0,0 +1,39 @@ +import { GetDatasetCitation } from '../../../src/datasets/domain/useCases/GetDatasetCitation'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + const testId = 1; + + afterEach(() => { + sandbox.restore(); + }); + + test('should return successful result with citation on repository success', async () => { + const testCitation = 'test citation'; + const datasetsRepositoryStub = {}; + const getDatasetCitationStub = sandbox.stub().returns(testCitation); + datasetsRepositoryStub.getDatasetCitation = getDatasetCitationStub; + + const sut = new GetDatasetCitation(datasetsRepositoryStub); + + const actual = await sut.execute(testId); + + assert.match(actual, testCitation); + assert.calledWithExactly(getDatasetCitationStub, testId, undefined); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getDatasetCitation = sandbox.stub().throwsException(testReadError); + const sut = new GetDatasetCitation(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute(testId).catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +}); diff --git a/test/unit/datasets/GetDatasetSummaryFieldNames.test.ts b/test/unit/datasets/GetDatasetSummaryFieldNames.test.ts new file mode 100644 index 00000000..c661cc29 --- /dev/null +++ b/test/unit/datasets/GetDatasetSummaryFieldNames.test.ts @@ -0,0 +1,35 @@ +import { GetDatasetSummaryFieldNames } from '../../../src/datasets/domain/useCases/GetDatasetSummaryFieldNames'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + + afterEach(() => { + sandbox.restore(); + }); + + test('should return successful result with field names on repository success', async () => { + const testFieldNames = ['test1', 'test2']; + const datasetsRepositoryStub = {}; + datasetsRepositoryStub.getDatasetSummaryFieldNames = sandbox.stub().returns(testFieldNames); + const sut = new GetDatasetSummaryFieldNames(datasetsRepositoryStub); + + const actual = await sut.execute(); + + assert.match(actual, testFieldNames); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getDatasetSummaryFieldNames = sandbox.stub().throwsException(testReadError); + const sut = new GetDatasetSummaryFieldNames(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute().catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +}); diff --git a/test/unit/datasets/GetPrivateUrlDataset.test.ts b/test/unit/datasets/GetPrivateUrlDataset.test.ts new file mode 100644 index 00000000..7f34232f --- /dev/null +++ b/test/unit/datasets/GetPrivateUrlDataset.test.ts @@ -0,0 +1,39 @@ +import { GetPrivateUrlDataset } from '../../../src/datasets/domain/useCases/GetPrivateUrlDataset'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; +import { createDatasetModel } from '../../testHelpers/datasets/datasetHelper'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + const testPrivateUrlToken = 'token'; + + afterEach(() => { + sandbox.restore(); + }); + + test('should return dataset on repository success', async () => { + const testDataset = createDatasetModel(); + const datasetsRepositoryStub = {}; + const getDatasetStub = sandbox.stub().returns(testDataset); + datasetsRepositoryStub.getPrivateUrlDataset = getDatasetStub; + const sut = new GetPrivateUrlDataset(datasetsRepositoryStub); + + const actual = await sut.execute(testPrivateUrlToken); + + assert.match(actual, testDataset); + assert.calledWithExactly(getDatasetStub, testPrivateUrlToken); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getPrivateUrlDataset = sandbox.stub().throwsException(testReadError); + const sut = new GetPrivateUrlDataset(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute(testPrivateUrlToken).catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +}); diff --git a/test/unit/datasets/GetPrivateUrlDatasetCitation.test.ts b/test/unit/datasets/GetPrivateUrlDatasetCitation.test.ts new file mode 100644 index 00000000..8aaac6a2 --- /dev/null +++ b/test/unit/datasets/GetPrivateUrlDatasetCitation.test.ts @@ -0,0 +1,39 @@ +import { GetPrivateUrlDatasetCitation } from '../../../src/datasets/domain/useCases/GetPrivateUrlDatasetCitation'; +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'; +import { ReadError } from '../../../src/core/domain/repositories/ReadError'; +import { assert, createSandbox, SinonSandbox } from 'sinon'; + +describe('execute', () => { + const sandbox: SinonSandbox = createSandbox(); + const testPrivateUrlToken = 'token'; + + afterEach(() => { + sandbox.restore(); + }); + + test('should return successful result with citation on repository success', async () => { + const testCitation = 'test citation'; + const datasetsRepositoryStub = {}; + const getPrivateUrlDatasetCitationStub = sandbox.stub().returns(testCitation); + datasetsRepositoryStub.getPrivateUrlDatasetCitation = getPrivateUrlDatasetCitationStub; + + const sut = new GetPrivateUrlDatasetCitation(datasetsRepositoryStub); + + const actual = await sut.execute(testPrivateUrlToken); + + assert.match(actual, testCitation); + assert.calledWithExactly(getPrivateUrlDatasetCitationStub, testPrivateUrlToken); + }); + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub = {}; + const testReadError = new ReadError(); + datasetsRepositoryStub.getPrivateUrlDatasetCitation = sandbox.stub().throwsException(testReadError); + const sut = new GetPrivateUrlDatasetCitation(datasetsRepositoryStub); + + let actualError: ReadError = undefined; + await sut.execute(testPrivateUrlToken).catch((e) => (actualError = e)); + + assert.match(actualError, testReadError); + }); +});