diff --git a/.github/workflows/DevelopServerDeploy.yml b/.github/workflows/DevelopServerDeploy.yml index 8ea849ad..ea5d57b6 100644 --- a/.github/workflows/DevelopServerDeploy.yml +++ b/.github/workflows/DevelopServerDeploy.yml @@ -14,10 +14,10 @@ jobs: - run: sudo apt-get update - run: sudo apt-get install -y libkrb5-dev - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm - name: Install node_modules @@ -36,10 +36,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm - name: Build action runner @@ -73,8 +73,8 @@ jobs: docker run -d --name wikigdrive-develop \ --restart unless-stopped \ -v wikiGDriveDevelop:/data \ - -v /home/githubactions/wikigdrive/service_account.json:/service_account.json \ - -v /home/githubactions/wikigdrive/env.develop:/usr/src/app/.env \ + -v /home/wikigdrive/service_account.json:/service_account.json \ + -v /home/wikigdrive/env.develop:/usr/src/app/.env \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "/var/www/dev.wikigdrive.com:/usr/src/app/dist/hugo" \ -e "GIT_SHA=${GITHUB_SHA}" \ diff --git a/.github/workflows/ProdServerDeploy.yml b/.github/workflows/ProdServerDeploy.yml index 2568af42..78faba12 100644 --- a/.github/workflows/ProdServerDeploy.yml +++ b/.github/workflows/ProdServerDeploy.yml @@ -15,10 +15,10 @@ jobs: - run: sudo apt-get update - run: sudo apt-get install -y libkrb5-dev - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm - name: Install node_modules @@ -37,10 +37,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm - name: Build action runner diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index b25763fd..414a289d 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -14,10 +14,10 @@ jobs: - run: sudo apt-get update - run: sudo apt-get install -y libkrb5-dev - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm - name: Install node_modules @@ -35,12 +35,15 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Use Node.js 18.x + - name: Use Node.js 20.x uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 cache: npm + - name: Build action runner + run: docker build -t "wgd-action-runner:test" --build-arg "GIT_SHA=${GITHUB_SHA}" apps/wgd-action-runner + - name: Build hugo docs run: | docker run \ @@ -48,7 +51,7 @@ jobs: -v "${GITHUB_WORKSPACE}/website:/website" \ -v "/var/www/test.wikigdrive.com:/dist/hugo" \ --env CONFIG_TOML="/site/config/_default/config.toml" --env BASE_URL="https://test.wikigdrive.com" \ - wgd-action-runner:develop /steps/step_render_hugo + wgd-action-runner:test /steps/step_render_hugo - name: Copy index for vite run: mkdir -p dist/hugo && cp -rf /var/www/test.wikigdrive.com/* dist/hugo @@ -65,4 +68,4 @@ jobs: continue-on-error: true - name: Start - run: docker run -t -v wikiGDriveExample:/data -v /home/githubactions/wikigdrive/service_account.json:/service_account.json -v "/var/www/dev.wikigdrive.com:/usr/src/app/dist/hugo" wikigdrive-test wikigdrive --service_account /service_account.json --share_email mie-docs-wikigdrive@wikigdrive.iam.gserviceaccount.com --workdir /data pull 0AIkOKXbzWCtSUk9PVA + run: docker run -t -v wikiGDriveExample:/data -v /home/wikigdrive/service_account.json:/service_account.json -v "/var/www/dev.wikigdrive.com:/usr/src/app/dist/hugo" wikigdrive-test wikigdrive --service_account /service_account.json --share_email mie-docs-wikigdrive@wikigdrive.iam.gserviceaccount.com --workdir /data pull 0AIkOKXbzWCtSUk9PVA diff --git a/.nvmrc b/.nvmrc index b460d6f2..d5a15960 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.12.1 +20.10.0 diff --git a/Dockerfile b/Dockerfile index c2995954..aad4058d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-alpine +FROM node:20-alpine RUN apk add --no-cache bash openssh-keygen git-lfs openssh-client WORKDIR /usr/src/app diff --git a/apps/ui/src/components/ChangesViewer.vue b/apps/ui/src/components/ChangesViewer.vue index 19c0c8bd..1ce8de6b 100644 --- a/apps/ui/src/components/ChangesViewer.vue +++ b/apps/ui/src/components/ChangesViewer.vue @@ -50,7 +50,6 @@ Jobs
-
Last full sync @@ -64,40 +63,26 @@
- +
- - + + + + + - - + + + + -
JobProgress
JobStartedFinished
{{ job.title }}{{ job.startedStr || job.state }}  {{ job.progress.completed }} / {{ job.progress.total }} - {{ job.state }} + Logs
- -
- No active jobs -
- -
- -
-
- Jobs done -
-
- - - - - - @@ -111,7 +96,6 @@
JobStartedFinished
{{ job.title }}
-
@@ -133,6 +117,18 @@ export default { }, components: {StatusToolBar}, computed: { + active_jobs_reverse() { + return [].concat(this.active_jobs) + .map(a => { + return { + ...a, + finishedStr: a.finished ? new Date(a.finished).toISOString() : undefined, + startedStr: a.started ? new Date(a.started).toISOString() : undefined, + durationStr: a.started && a.finished ? Math.round((+new Date(a.finished) - +new Date(a.started)) / 100)/10 + 's' : undefined + }; + }) + .reverse(); + }, fileChanges() { return this.changes.filter(change => change.mimeType !== 'application/vnd.google-apps.folder'); }, diff --git a/apps/ui/src/components/JobLogsViewer.vue b/apps/ui/src/components/JobLogsViewer.vue index 345d7647..1e5f8dbc 100644 --- a/apps/ui/src/components/JobLogsViewer.vue +++ b/apps/ui/src/components/JobLogsViewer.vue @@ -22,7 +22,7 @@ import {UtilsMixin} from './UtilsMixin.ts'; import StatusToolBar from './StatusToolBar.vue'; -import {Prism} from './prismFix'; +// import {Prism} from './prismFix'; export default { mixins: [UtilsMixin], @@ -36,15 +36,22 @@ export default { }, contentDir: { type: String + }, + autoRefresh: { + type: Boolean } }, data() { return { errorsOnly: false, - logs: [] + logs: [], + intervalHandle: null }; }, computed: { + currentJob() { + return this.$root.jobs.find(job => 'job-' + job.id === this.jobId); + }, absPath() { return '/drive/' + this.driveId + this.contentDir; }, @@ -63,13 +70,19 @@ export default { } const jobId = this.jobId.substring('job-'.length); - const response = await this.authenticatedClient.fetchApi(`/api/logs/${this.driveId}?order=asc&jobId=` + (jobId)); + const response = await this.authenticatedClient.fetchApi(`/api/logs/${this.driveId}?order=asc&jobId=` + (jobId) + '&offset=' + this.logs.length); const logs = await response.json(); + + if (this.intervalHandle && this.currentJob && this.currentJob.finished) { + clearInterval(this.intervalHandle); + this.intervalHandle = null; + } + if (logs.length === 0) { return; } - this.logs = logs; + this.logs = this.logs.concat(logs); if (logs.length > 0) { this.handleScroll(); @@ -109,7 +122,8 @@ export default { return new Date(v).toISOString(); }, highLight(str) { - return Prism.highlight(str, Prism.languages.markdown, 'markdown'); + return str; + // FIXME: return Prism.highlight(str, Prism.languages.markdown, 'markdown'); }, rewriteLinks() { const links = this.$el.querySelectorAll('a[data-to-rewrite]'); @@ -138,6 +152,18 @@ export default { this.handleScroll(); // Prism.highlightElement(this.$refs.code); + if (!this.intervalHandle && this.currentJob && !this.currentJob.finished) { + this.intervalHandle = setInterval(() => { + this.fetch(); + }, 1000); + } + }, + beforeUnmount() { + if (!this.intervalHandle) { + return; + } + clearInterval(this.intervalHandle); + this.intervalHandle = null; } }; diff --git a/apps/ui/src/components/UserSettings.vue b/apps/ui/src/components/UserSettings.vue index b2923d02..d9468356 100644 --- a/apps/ui/src/components/UserSettings.vue +++ b/apps/ui/src/components/UserSettings.vue @@ -55,6 +55,11 @@ + +
+ + +

diff --git a/apps/ui/src/components/ZipkinViewer.vue b/apps/ui/src/components/ZipkinViewer.vue index 9662eadd..e533b508 100644 --- a/apps/ui/src/components/ZipkinViewer.vue +++ b/apps/ui/src/components/ZipkinViewer.vue @@ -52,7 +52,7 @@ export default { data() { return { traces: [], - ZIPKIN_URL + ZIPKIN_URL: ZIPKIN_URL.startsWith('http://localhost:9411') ? ZIPKIN_URL + '/zipkin' : ZIPKIN_URL }; }, created() { diff --git a/apps/ui/src/services/CachedFileClientService.ts b/apps/ui/src/services/CachedFileClientService.ts index 109df006..0b1f42c5 100644 --- a/apps/ui/src/services/CachedFileClientService.ts +++ b/apps/ui/src/services/CachedFileClientService.ts @@ -1,7 +1,7 @@ -import {FileClientService} from './FileClientService.js'; +import {FileClientService} from './FileClientService.ts'; export class CachedFileClientService extends FileClientService { - private cache: any; + private cache: unknown; constructor(authenticatedClient) { super(authenticatedClient); diff --git a/apps/ui/tsconfig.json b/apps/ui/tsconfig.json index eee7354c..85a14105 100644 --- a/apps/ui/tsconfig.json +++ b/apps/ui/tsconfig.json @@ -4,6 +4,7 @@ "module": "ESNext", "moduleResolution": "node", "target": "ESNext", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "esModuleInterop": true, "sourceMap": true, diff --git a/package-lock.json b/package-lock.json index fde8ec14..ddaf9574 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,6 @@ "@opentelemetry/context-zone": "1.8.0", "@opentelemetry/exporter-zipkin": "1.8.0", "@opentelemetry/instrumentation": "0.33.0", - "@opentelemetry/instrumentation-express": "0.31.3", "@opentelemetry/instrumentation-fetch": "0.34.0", "@opentelemetry/instrumentation-http": "0.34.0", "@opentelemetry/resources": "1.8.0", @@ -62,7 +61,7 @@ "slugify": "1.6.5", "stream": "^0.0.2", "ts-node": "10.9.1", - "typescript": "4.9.4", + "typescript": "5.3.2", "vite": "4.0.1", "winston": "3.8.2", "winston-transport": "4.5.0", @@ -84,24 +83,24 @@ "@types/express": "4.17.13", "@types/lunr": "2.3.4", "@types/mocha": "10.0.2", - "@types/node": "18.11.12", + "@types/node": "20.10.0", "@types/passport": "1.0.9", "@types/relateurl": "0.2.29", "@types/ws": "8.5.3", "@types/xmldoc": "^1.1.5", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", + "@typescript-eslint/eslint-plugin": "6.12.0", + "@typescript-eslint/parser": "6.12.0", "chai": "4.3.6", "diff": "5.0.0", - "eslint": "^8.11.0", + "eslint": "8.54.0", "husky": "7.0.4", "jshint": "2.13.4", "mocha": "10.2.0", "sinon": "13.0.1" }, "engines": { - "node": ">= 18.12.0", - "npm": ">= 8.1.2" + "node": ">= 20.10.0", + "npm": ">= 10.2.3" } }, "apps/ui": { @@ -509,6 +508,19 @@ "@esbuild/win32-x64": "0.18.20" } }, + "apps/ui/node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "apps/ui/node_modules/vite": { "version": "4.4.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", @@ -564,6 +576,15 @@ } } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/parser": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", @@ -945,44 +966,105 @@ "node": ">=12" } }, + "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.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@jridgewell/resolve-uri": { @@ -1148,51 +1230,6 @@ "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.31.3.tgz", - "integrity": "sha512-+uta+Esj2r7oRXN2xLyI45JahbTCi07A6KpwvJZGKFaQg6nDBdWyfDdj5s1h2N13IsbFbcQqK4vidTeCcRuR8Q==", - "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/semantic-conventions": "^1.0.0", - "@types/express": "4.17.13" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/instrumentation-express/node_modules/@opentelemetry/api-metrics": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-metrics/-/api-metrics-0.32.0.tgz", - "integrity": "sha512-g1WLhpG8B6iuDyZJFRGsR+JKyZ94m5LEmY2f+duEJ9Xb4XRlLHrZvh6G34OH6GJ8iDHxfHb/sWjJ1ZpkI9yGMQ==", - "dependencies": { - "@opentelemetry/api": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/instrumentation-express/node_modules/@opentelemetry/instrumentation": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.32.0.tgz", - "integrity": "sha512-y6ADjHpkUz/v1nkyyYjsQa/zorhX+0qVGpFvXMcbjU4sHnBnC02c6wcc93sIgZfiQClIWo45TGku1KQxJ5UUbQ==", - "dependencies": { - "@opentelemetry/api-metrics": "0.32.0", - "require-in-the-middle": "^5.0.3", - "semver": "^7.3.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, "node_modules/@opentelemetry/instrumentation-fetch": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fetch/-/instrumentation-fetch-0.34.0.tgz", @@ -1640,6 +1677,7 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -1658,6 +1696,7 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -1686,6 +1725,7 @@ "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -1694,19 +1734,21 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.27", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.27.tgz", - "integrity": "sha512-e/sVallzUTPdyOTiqi8O8pMdBBphscvI6E4JYaKlja4Lm+zh7UFSSdW5VMkRbhDtmrONqOUHOXRguPsDckzxNA==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/jsonwebtoken": { @@ -1726,7 +1768,8 @@ "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true }, "node_modules/@types/mocha": { "version": "10.0.2", @@ -1735,9 +1778,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz", - "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg==" + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/passport": { "version": "1.0.9", @@ -1751,12 +1797,14 @@ "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true }, "node_modules/@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true }, "node_modules/@types/relateurl": { "version": "0.2.29", @@ -1764,10 +1812,27 @@ "integrity": "sha512-QSvevZ+IRww2ldtfv1QskYsqVVVwCKQf1XbwtcyyoRvLIQzfyPhj/C+3+PKzSDRdiyejaiLgnq//XTkleorpLg==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/serve-static": { "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -1798,31 +1863,33 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz", - "integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "5.9.0", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/type-utils": "5.9.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1830,50 +1897,27 @@ } } }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz", - "integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz", - "integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "debug": "^4.3.2" + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1882,16 +1926,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -1899,24 +1943,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz", - "integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "5.9.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1925,12 +1970,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -1938,21 +1983,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", - "debug": "^4.3.2", - "globby": "^11.0.4", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -1964,23 +2009,54 @@ } } }, + "node_modules/@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-vue": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz", @@ -2118,9 +2194,9 @@ } }, "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "bin": { "acorn": "bin/acorn" }, @@ -3314,46 +3390,49 @@ } }, "node_modules/eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "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.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -3386,16 +3465,19 @@ } }, "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { @@ -3426,12 +3508,15 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/chalk": { @@ -3450,28 +3535,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3484,24 +3547,39 @@ "node": ">=10.13.0" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -3510,15 +3588,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -3531,19 +3600,10 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { "node": ">=4.0" @@ -3698,9 +3758,9 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.8.tgz", - "integrity": "sha512-UsiHHXoDbC3iS7vBOFvld7Q9XqBu318xztdHiL10Fjov3AK5GI5bek2ZJkxZcjPguOYH39UL1W4A6w+l7tpNtw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3710,25 +3770,25 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3914,12 +3974,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3976,9 +4030,9 @@ } }, "node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -3991,16 +4045,16 @@ } }, "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { @@ -4010,6 +4064,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4123,9 +4183,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -4137,9 +4197,9 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" }, "node_modules/import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -4147,6 +4207,9 @@ }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { @@ -4261,6 +4324,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -4815,13 +4887,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -5187,17 +5259,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -5480,9 +5552,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -5602,18 +5674,6 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, - "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/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -6320,6 +6380,18 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -6370,27 +6442,6 @@ "node": ">=0.3.1" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "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/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6461,17 +6512,22 @@ } }, "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -6481,9 +6537,9 @@ } }, "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "punycode": "^2.1.0" @@ -6502,12 +6558,6 @@ "node": ">= 0.4.0" } }, - "node_modules/v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -6605,28 +6655,6 @@ "eslint": ">=6.0.0" } }, - "node_modules/vue-eslint-parser/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==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/vue-prism-editor": { "version": "2.0.0-alpha.2", "resolved": "https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-2.0.0-alpha.2.tgz", @@ -6727,15 +6755,6 @@ "node": ">= 6" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", @@ -6893,6 +6912,12 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@babel/parser": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", @@ -7061,38 +7086,76 @@ "integrity": "sha512-sN/I8FMPtmtT2Yw+Dly8Ur5vQ5a/RmC8hW7jO9PtPSQUPkowxWpcUZnqOggU7VwyT3Xkj6vcXWd3V/qTXwultQ==", "optional": true }, + "@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, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@jridgewell/resolve-uri": { @@ -7310,6 +7373,12 @@ "@esbuild/win32-x64": "0.18.20" } }, + "typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true + }, "vite": { "version": "4.4.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", @@ -7414,38 +7483,6 @@ "shimmer": "^1.2.1" } }, - "@opentelemetry/instrumentation-express": { - "version": "0.31.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.31.3.tgz", - "integrity": "sha512-+uta+Esj2r7oRXN2xLyI45JahbTCi07A6KpwvJZGKFaQg6nDBdWyfDdj5s1h2N13IsbFbcQqK4vidTeCcRuR8Q==", - "requires": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/instrumentation": "^0.32.0", - "@opentelemetry/semantic-conventions": "^1.0.0", - "@types/express": "4.17.13" - }, - "dependencies": { - "@opentelemetry/api-metrics": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-metrics/-/api-metrics-0.32.0.tgz", - "integrity": "sha512-g1WLhpG8B6iuDyZJFRGsR+JKyZ94m5LEmY2f+duEJ9Xb4XRlLHrZvh6G34OH6GJ8iDHxfHb/sWjJ1ZpkI9yGMQ==", - "requires": { - "@opentelemetry/api": "^1.0.0" - } - }, - "@opentelemetry/instrumentation": { - "version": "0.32.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.32.0.tgz", - "integrity": "sha512-y6ADjHpkUz/v1nkyyYjsQa/zorhX+0qVGpFvXMcbjU4sHnBnC02c6wcc93sIgZfiQClIWo45TGku1KQxJ5UUbQ==", - "requires": { - "@opentelemetry/api-metrics": "0.32.0", - "require-in-the-middle": "^5.0.3", - "semver": "^7.3.2", - "shimmer": "^1.2.1" - } - } - } - }, "@opentelemetry/instrumentation-fetch": { "version": "0.34.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fetch/-/instrumentation-fetch-0.34.0.tgz", @@ -7731,6 +7768,7 @@ "version": "1.19.2", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, "requires": { "@types/connect": "*", "@types/node": "*" @@ -7749,6 +7787,7 @@ "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, "requires": { "@types/node": "*" } @@ -7777,6 +7816,7 @@ "version": "4.17.13", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, "requires": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.18", @@ -7785,19 +7825,21 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.27", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.27.tgz", - "integrity": "sha512-e/sVallzUTPdyOTiqi8O8pMdBBphscvI6E4JYaKlja4Lm+zh7UFSSdW5VMkRbhDtmrONqOUHOXRguPsDckzxNA==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dev": true, "requires": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "@types/jsonwebtoken": { @@ -7817,7 +7859,8 @@ "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true }, "@types/mocha": { "version": "10.0.2", @@ -7826,9 +7869,12 @@ "dev": true }, "@types/node": { - "version": "18.11.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz", - "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg==" + "version": "20.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", + "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/passport": { "version": "1.0.9", @@ -7842,12 +7888,14 @@ "@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true }, "@types/range-parser": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true }, "@types/relateurl": { "version": "0.2.29", @@ -7855,10 +7903,27 @@ "integrity": "sha512-QSvevZ+IRww2ldtfv1QskYsqVVVwCKQf1XbwtcyyoRvLIQzfyPhj/C+3+PKzSDRdiyejaiLgnq//XTkleorpLg==", "dev": true }, + "@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/serve-static": { "version": "1.13.10", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, "requires": { "@types/mime": "^1", "@types/node": "*" @@ -7889,100 +7954,111 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz", - "integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "5.9.0", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/type-utils": "5.9.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz", - "integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", + "integrity": "sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/type-utils": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/parser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz", - "integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz", + "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.9.0", - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/typescript-estree": "5.9.0", - "debug": "^4.3.2" + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz", - "integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz", + "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0" + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0" } }, "@typescript-eslint/type-utils": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz", - "integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz", + "integrity": "sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "5.9.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" + "@typescript-eslint/typescript-estree": "6.12.0", + "@typescript-eslint/utils": "6.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz", - "integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz", + "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz", - "integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz", + "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.9.0", - "@typescript-eslint/visitor-keys": "5.9.0", - "debug": "^4.3.2", - "globby": "^11.0.4", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/visitor-keys": "6.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.12.0.tgz", + "integrity": "sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.12.0", + "@typescript-eslint/types": "6.12.0", + "@typescript-eslint/typescript-estree": "6.12.0", + "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz", - "integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz", + "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.9.0", - "eslint-visitor-keys": "^3.0.0" + "@typescript-eslint/types": "6.12.0", + "eslint-visitor-keys": "^3.4.1" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "@vitejs/plugin-vue": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz", @@ -8108,9 +8184,9 @@ } }, "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==" }, "acorn-jsx": { "version": "5.3.2", @@ -9019,46 +9095,49 @@ "dev": true }, "eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "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.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "chalk": { @@ -9071,22 +9150,6 @@ "supports-color": "^7.1.0" } }, - "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==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -9095,6 +9158,15 @@ "requires": { "is-glob": "^4.0.3" } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -9113,13 +9185,13 @@ } }, "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" } }, "eslint-utils": { @@ -9140,37 +9212,29 @@ } }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" } }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "esrecurse": { @@ -9180,20 +9244,12 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "estree-walker": { @@ -9318,9 +9374,9 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "fast-glob": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.8.tgz", - "integrity": "sha512-UsiHHXoDbC3iS7vBOFvld7Q9XqBu318xztdHiL10Fjov3AK5GI5bek2ZJkxZcjPguOYH39UL1W4A6w+l7tpNtw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -9331,21 +9387,21 @@ } }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -9488,12 +9544,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -9535,28 +9585,34 @@ } }, "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" } }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -9625,9 +9681,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, "immediate": { @@ -9636,9 +9692,9 @@ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -9724,6 +9780,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "devOptional": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -10183,13 +10245,13 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "mime-db": { @@ -10461,17 +10523,17 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" } }, "p-limit": { @@ -10663,9 +10725,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { @@ -10757,12 +10819,6 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -11285,6 +11341,13 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, "ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -11312,21 +11375,6 @@ } } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11376,9 +11424,14 @@ "integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==" }, "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==" + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "unpipe": { "version": "1.0.0", @@ -11386,9 +11439,9 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -11404,12 +11457,6 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, - "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", - "dev": true - }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -11457,24 +11504,6 @@ "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.5" - }, - "dependencies": { - "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==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } } }, "vue-prism-editor": { @@ -11552,12 +11581,6 @@ } } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", diff --git a/package.json b/package.json index e0dcf17b..d34ddc89 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "Wiki" ], "engines": { - "node": ">= 18.12.0", - "npm": ">= 8.1.2" + "node": ">= 20.10.0", + "npm": ">= 10.2.3" }, "bin": { "wgd": "src/wikigdrive.sh", @@ -71,7 +71,6 @@ "@opentelemetry/context-zone": "1.8.0", "@opentelemetry/exporter-zipkin": "1.8.0", "@opentelemetry/instrumentation": "0.33.0", - "@opentelemetry/instrumentation-express": "0.31.3", "@opentelemetry/instrumentation-fetch": "0.34.0", "@opentelemetry/instrumentation-http": "0.34.0", "@opentelemetry/resources": "1.8.0", @@ -117,7 +116,7 @@ "slugify": "1.6.5", "stream": "^0.0.2", "ts-node": "10.9.1", - "typescript": "4.9.4", + "typescript": "5.3.2", "vite": "4.0.1", "winston": "3.8.2", "winston-transport": "4.5.0", @@ -134,16 +133,16 @@ "@types/express": "4.17.13", "@types/lunr": "2.3.4", "@types/mocha": "10.0.2", - "@types/node": "18.11.12", + "@types/node": "20.10.0", "@types/passport": "1.0.9", "@types/relateurl": "0.2.29", "@types/ws": "8.5.3", "@types/xmldoc": "^1.1.5", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", + "@typescript-eslint/eslint-plugin": "6.12.0", + "@typescript-eslint/parser": "6.12.0", "chai": "4.3.6", "diff": "5.0.0", - "eslint": "^8.11.0", + "eslint": "8.54.0", "husky": "7.0.4", "jshint": "2.13.4", "mocha": "10.2.0", diff --git a/src/containers/google_folder/UploadContainer.ts b/src/containers/google_folder/UploadContainer.ts index fa47be96..63ccdb16 100644 --- a/src/containers/google_folder/UploadContainer.ts +++ b/src/containers/google_folder/UploadContainer.ts @@ -4,20 +4,20 @@ import * as htmlparser2 from 'htmlparser2'; import {ElementType} from 'htmlparser2'; import * as domutils from 'domutils'; import {Element, Text} from 'domhandler'; - import render from 'dom-serializer'; -import {FileId} from '../../model/model'; -import {MimeTypes} from '../../model/GoogleFile'; -import {LocalFile} from '../../model/LocalFile'; -import {Container, ContainerConfig, ContainerConfigArr, ContainerEngine} from '../../ContainerEngine'; -import {GoogleDriveService} from '../../google/GoogleDriveService'; -import {UserConfigService} from './UserConfigService'; -import {FileContentService} from '../../utils/FileContentService'; -import {getContentFileService} from '../transform/utils'; -import {DirectoryScanner} from '../transform/DirectoryScanner'; -import {getDesiredPath} from '../transform/LocalFilesGenerator'; -import {markdownToHtml} from '../../google/markdownToHtml'; -import {convertToAbsolutePath} from '../../LinkTranslator'; + +import {FileId} from '../../model/model.ts'; +import {MimeTypes} from '../../model/GoogleFile.ts'; +import {LocalFile} from '../../model/LocalFile.ts'; +import {Container, ContainerConfig, ContainerConfigArr, ContainerEngine} from '../../ContainerEngine.ts'; +import {GoogleDriveService} from '../../google/GoogleDriveService.ts'; +import {UserConfigService} from './UserConfigService.ts'; +import {FileContentService} from '../../utils/FileContentService.ts'; +import {getContentFileService} from '../transform/utils.ts'; +import {DirectoryScanner} from '../transform/DirectoryScanner.ts'; +import {getDesiredPath} from '../transform/LocalFilesGenerator.ts'; +import {markdownToHtml} from '../../google/markdownToHtml.ts'; +import {convertToAbsolutePath} from '../../LinkTranslator.ts'; const __filename = fileURLToPath(import.meta.url); @@ -85,6 +85,7 @@ export class UploadContainer extends Container { case MimeTypes.MARKDOWN: if (file.id === 'TO_FILL') { file.id = ids.splice(0, 1)[0]; + file['isNewId'] = true; } break; } @@ -133,15 +134,27 @@ export class UploadContainer extends Container { const html = await markdownToHtml(content); entry.performRewrite = html; const buffer = Buffer.from(new TextEncoder().encode(html)); - const response = await this.googleDriveService.upload(access_token, entry.parent, file.title, MimeTypes.HTML, buffer); - file.id = response.id; + if (file['isNewId']) { + const response = await this.googleDriveService.upload(access_token, entry.parent, file.title, MimeTypes.HTML, buffer); // generatedIds not supported to gdocs + file.id = response.id; + delete file['isNewId']; + } else { + const response = await this.googleDriveService.update(access_token, entry.parent, file.title, MimeTypes.HTML, buffer, file.id); + file.id = response.id; + } } break; case MimeTypes.IMAGE_SVG: if (file.id && file.id !== 'TO_FILL') { const content = await dirFileService.readBuffer(entry.path); - const response = await this.googleDriveService.upload(access_token, entry.parent, file.title, file.mimeType, content, file.id); - file.id = response.id; + if (file['isNewId']) { + const response = await this.googleDriveService.upload(access_token, entry.parent, file.title, file.mimeType, content, file.id); + file.id = response.id; + delete file['isNewId']; + } else { + const response = await this.googleDriveService.update(access_token, entry.parent, file.title, file.mimeType, content, file.id); + file.id = response.id; + } } break; } @@ -194,23 +207,26 @@ export class UploadContainer extends Container { case MimeTypes.MARKDOWN: if (map[getDesiredPath(file.title)]) { file.id = map[getDesiredPath(file.title)].id; + } else { // Upload only missing + file.id = 'TO_FILL'; + retVal.push({ + path: parentPath + '/' + file.fileName, + file, + parent: folderId + }); } - retVal.push({ - path: parentPath + '/' + file.fileName, - file, - parent: folderId - }); break; case MimeTypes.IMAGE_SVG: if (map[getDesiredPath(file.title)]) { file.id = map[getDesiredPath(file.title)].id; + } else { // Upload only missing + file.id = 'TO_FILL'; + retVal.push({ + path: parentPath + '/' + file.fileName, + file, + parent: folderId + }); } - - retVal.push({ - path: parentPath + '/' + file.fileName, - file, - parent: folderId - }); break; } diff --git a/src/containers/google_folder/UserConfigService.ts b/src/containers/google_folder/UserConfigService.ts index 0c8c6a32..e1fc25d1 100644 --- a/src/containers/google_folder/UserConfigService.ts +++ b/src/containers/google_folder/UserConfigService.ts @@ -2,10 +2,11 @@ import path from 'path'; import fs from 'fs'; import {exec} from 'child_process'; import yaml from 'js-yaml'; -import {FileContentService} from '../../utils/FileContentService'; -import {HugoTheme} from '../server/routes/ConfigController'; -import {FRONTMATTER_DUMP_OPTS} from '../transform/frontmatters/frontmatter'; -import {DEFAULT_ACTIONS} from '../action/ActionRunnerContainer'; +import {FileContentService} from '../../utils/FileContentService.ts'; +import {HugoTheme} from '../server/routes/ConfigController.ts'; +import {FRONTMATTER_DUMP_OPTS} from '../transform/frontmatters/frontmatter.ts'; +import {DEFAULT_ACTIONS} from '../action/ActionRunnerContainer.ts'; +import {RewriteRule} from '../../odt/applyRewriteRule.js'; async function execAsync(command: string) { const err = new Error(); @@ -40,6 +41,7 @@ export class UserConfig { auto_sync?: boolean; fm_without_version?: boolean; actions_yaml?: string; + rewrite_rules?: RewriteRule[]; } const DEFAULT_CONFIG: UserConfig = { @@ -52,6 +54,19 @@ const DEFAULT_CONFIG: UserConfig = { } }; +const DEFAULT_REWRITE_RULES = [ + { + tag: 'A', + match: '$alt', + template: '$href' + }, + { + match: '(?:https?:\\/\\/)?(?:www\\.)?(?:youtube\\.com\\/(?:[^\\/\\n\\s]+\\/\\S+\\/|(?:v|e(?:mbed)?)\\/|\\S*?[?&]v=)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})', + replace: '(?:https?:\\/\\/)?(?:www\\.)?(?:youtube\\.com\\/(?:[^\\/\\n\\s]+\\/\\S+\\/|(?:v|e(?:mbed)?)\\/|\\S*?[?&]v=)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})', + template: '[$label](https://youtube.be/$value)' + } +]; + export class UserConfigService { public config: UserConfig; @@ -69,6 +84,9 @@ export class UserConfigService { if (!this.config.actions_yaml) { this.config.actions_yaml = yaml.dump(DEFAULT_ACTIONS, FRONTMATTER_DUMP_OPTS); } + if (!this.config.rewrite_rules || this.config.rewrite_rules.length === 0) { + this.config.rewrite_rules = DEFAULT_REWRITE_RULES; + } return this.config; } diff --git a/src/containers/job/JobManagerContainer.ts b/src/containers/job/JobManagerContainer.ts index b3eb147c..64606412 100644 --- a/src/containers/job/JobManagerContainer.ts +++ b/src/containers/job/JobManagerContainer.ts @@ -4,8 +4,6 @@ import {GoogleFolderContainer} from '../google_folder/GoogleFolderContainer'; import {TransformContainer} from '../transform/TransformContainer'; import {fileURLToPath} from 'url'; -import {WatchChangesContainer} from '../changes/WatchChangesContainer'; -import {GoogleFile} from '../../model/GoogleFile'; import {UserConfigService} from '../google_folder/UserConfigService'; import {MarkdownTreeProcessor} from '../transform/MarkdownTreeProcessor'; import {WorkerPool} from './WorkerPool'; diff --git a/src/containers/server/ServerContainer.ts b/src/containers/server/ServerContainer.ts index bc2a0cf9..7de4a0f6 100644 --- a/src/containers/server/ServerContainer.ts +++ b/src/containers/server/ServerContainer.ts @@ -1,28 +1,31 @@ -import {Container, ContainerConfig, ContainerEngine} from '../../ContainerEngine'; -import express, {Express, NextFunction} from 'express'; +import type {Express, NextFunction, Request, Response} from 'express'; +import express from 'express'; import http from 'http'; import {WebSocketServer} from 'ws'; import winston from 'winston'; import path from 'path'; -import {FileId} from '../../model/model'; -import {saveRunningInstance} from './loadRunningInstance'; -import {urlToFolderId} from '../../utils/idParsers'; -import {GoogleDriveService} from '../../google/GoogleDriveService'; -import {FolderRegistryContainer} from '../folder_registry/FolderRegistryContainer'; -import {DriveJobsMap, initJob, JobManagerContainer} from '../job/JobManagerContainer'; import {fileURLToPath} from 'url'; -import GitController from './routes/GitController'; -import FolderController from './routes/FolderController'; -import {ConfigController} from './routes/ConfigController'; -import {DriveController} from './routes/DriveController'; -import {BackLinksController} from './routes/BackLinksController'; -import {GoogleDriveController} from './routes/GoogleDriveController'; -import {LogsController} from './routes/LogsController'; -import {PreviewController} from './routes/PreviewController'; import cookieParser from 'cookie-parser'; import rateLimit from 'express-rate-limit'; +import compress from 'compression'; -import {SocketManager} from './SocketManager'; +import {Container, ContainerConfig, ContainerEngine} from '../../ContainerEngine.ts'; +import {FileId} from '../../model/model.ts'; +import {saveRunningInstance} from './loadRunningInstance.ts'; +import {urlToFolderId} from '../../utils/idParsers.ts'; +import {GoogleDriveService} from '../../google/GoogleDriveService.ts'; +import {FolderRegistryContainer} from '../folder_registry/FolderRegistryContainer.ts'; +import {DriveJobsMap, initJob, JobManagerContainer} from '../job/JobManagerContainer.ts'; +import GitController from './routes/GitController.ts'; +import FolderController from './routes/FolderController.ts'; +import {ConfigController} from './routes/ConfigController.ts'; +import {DriveController} from './routes/DriveController.ts'; +import {BackLinksController} from './routes/BackLinksController.ts'; +import {GoogleDriveController} from './routes/GoogleDriveController.ts'; +import {LogsController} from './routes/LogsController.ts'; +import {PreviewController} from './routes/PreviewController.ts'; + +import {SocketManager} from './SocketManager.ts'; import { authenticate, @@ -31,19 +34,17 @@ import { authenticateOptionally, validateGetAuthState, handleDriveUiInstall, handleShare, handlePopupClose, redirError -} from './auth'; -import {filterParams} from '../../google/driveFetch'; -import {SearchController} from './routes/SearchController'; -import opentelemetry from '@opentelemetry/api'; -import {DriveUiController} from './routes/DriveUiController'; -import {GoogleApiContainer} from '../google_api/GoogleApiContainer'; -import {UserAuthClient} from '../../google/AuthClient'; -import {getTokenInfo} from '../../google/GoogleAuthService'; -import {GoogleTreeProcessor} from '../google_folder/GoogleTreeProcessor'; -import compress from 'compression'; -import {initStaticDistPages} from './static'; -import {initUiServer} from './vuejs'; -import {initErrorHandler} from './error'; +} from './auth.ts'; +import {filterParams} from '../../google/driveFetch.ts'; +import {SearchController} from './routes/SearchController.ts'; +import {DriveUiController} from './routes/DriveUiController.ts'; +import {GoogleApiContainer} from '../google_api/GoogleApiContainer.ts'; +import {UserAuthClient} from '../../google/AuthClient.ts'; +import {getTokenInfo} from '../../google/GoogleAuthService.ts'; +import {GoogleTreeProcessor} from '../google_folder/GoogleTreeProcessor.ts'; +import {initStaticDistPages} from './static.ts'; +import {initUiServer} from './vuejs.ts'; +import {initErrorHandler} from './error.ts'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -59,6 +60,14 @@ interface TreeItem { export const isHtml = req => req.headers.accept.indexOf('text/html') > -1; +function getDurationInMilliseconds(start) { + const NS_PER_SEC = 1e9; + const NS_TO_MS = 1e6; + const diff = process.hrtime(start); + + return Math.round((diff[0] * NS_PER_SEC + diff[1]) / NS_TO_MS); +} + export class ServerContainer extends Container { private logger: winston.Logger; private app: Express; @@ -97,20 +106,8 @@ export class ServerContainer extends Container { next(); }); - if (process.env.ZIPKIN_URL) { - app.use((req, res, next) => { - if (req.header('traceparent')) { - next(); - return; - } - - const span = opentelemetry.trace.getActiveSpan(); - if (span) { - const traceId = span.spanContext().traceId; - res.header('trace-id', traceId); - } - next(); - }); + if (express['addExpressTelemetry']) { + express['addExpressTelemetry'](app); } app.use(rateLimit({ @@ -224,9 +221,13 @@ export class ServerContainer extends Container { } async initRouter(app) { - app.use(async (req: express.Request, res: express.Response, next: NextFunction) => { + app.use(async (req: Request, res: Response, next: NextFunction) => { if (req.path.startsWith('/api/')) { - this.logger.info(`${req.method} ${req.path}`); + const start = process.hrtime(); + res.on('finish', () => { + const durationInMilliseconds = getDurationInMilliseconds(start); + this.logger.info(`${req.method} ${req.originalUrl} ${durationInMilliseconds}ms`); + }); } next(); }); diff --git a/src/containers/server/auth.ts b/src/containers/server/auth.ts index 6258c7bd..82c70036 100644 --- a/src/containers/server/auth.ts +++ b/src/containers/server/auth.ts @@ -2,7 +2,7 @@ import jsonwebtoken from 'jsonwebtoken'; import {decrypt, encrypt} from '../../google/GoogleAuthService'; import {GoogleDriveService} from '../../google/GoogleDriveService'; import {Logger} from 'winston'; -import {Request, Response} from 'express'; +import type {Request, Response} from 'express'; import {UserAuthClient} from '../../google/AuthClient'; import {FolderRegistryContainer} from '../folder_registry/FolderRegistryContainer'; import {urlToFolderId} from '../../utils/idParsers'; diff --git a/src/containers/server/error.ts b/src/containers/server/error.ts index c8f93006..6d01129b 100644 --- a/src/containers/server/error.ts +++ b/src/containers/server/error.ts @@ -1,11 +1,11 @@ -import express, {NextFunction, Request, Response} from 'express'; +import type {Application, NextFunction, Request, Response} from 'express'; import winston from 'winston'; import {GoogleDriveServiceError} from '../../google/driveFetch'; import {AuthError} from './auth'; import {handleStaticHtml} from './static'; -export async function initErrorHandler(app: express.Application, logger: winston.Logger) { +export async function initErrorHandler(app: Application, logger: winston.Logger) { app.use(async (err: GoogleDriveServiceError & AuthError, req: Request, res: Response, next: NextFunction) => { const code = err.status || 501; logger.warn(`http error ${code} for: ${req.originalUrl}`); diff --git a/src/containers/server/routes/ConfigController.ts b/src/containers/server/routes/ConfigController.ts index 2be06815..4807f48f 100644 --- a/src/containers/server/routes/ConfigController.ts +++ b/src/containers/server/routes/ConfigController.ts @@ -1,3 +1,5 @@ +import yaml from 'js-yaml'; + import {Controller, RouteGet, RouteParamBody, RouteParamPath, RoutePost, RoutePut} from './Controller'; import {FileContentService} from '../../../utils/FileContentService'; import {GitScanner} from '../../../git/GitScanner'; @@ -10,6 +12,7 @@ export interface ConfigBody { remote_branch: string; config_toml?: string; transform_subdir?: string; + rewrite_rules_yaml?: string; hugo_theme: HugoTheme; auto_sync: boolean; fm_without_version: boolean; @@ -47,7 +50,7 @@ export class ConfigController extends Controller { const hugo_themes = await loadHugoThemes(this.filesService); return { - config: userConfigService.config, + config: { ...userConfigService.config, rewrite_rules_yaml: yaml.dump(userConfigService.config.rewrite_rules || []) }, public_key: await userConfigService.getDeployKey(), hugo_themes }; @@ -90,6 +93,9 @@ export class ConfigController extends Controller { if (body.config?.config_toml) { userConfigService.config.config_toml = body.config?.config_toml; } + if (body.config?.rewrite_rules_yaml) { + userConfigService.config.rewrite_rules = yaml.load(body.config?.rewrite_rules_yaml); + } let modified = false; if ('string' === typeof body.config?.transform_subdir) { let trimmed = body.config?.transform_subdir.trim(); diff --git a/src/containers/server/routes/Controller.ts b/src/containers/server/routes/Controller.ts index 7ed1cb31..8a89a6da 100644 --- a/src/containers/server/routes/Controller.ts +++ b/src/containers/server/routes/Controller.ts @@ -1,6 +1,8 @@ -import express, { Router } from 'express'; +import type { Router } from 'express'; +import type * as express from 'express'; import SwaggerDocService from './SwaggerDocService'; import winston from 'winston'; +import {instrumentAndWrap} from '../../../telemetry'; // import SwaggerDocService from '../api-docs.api/SwaggerDocService'; export const HttpStatus = { @@ -168,6 +170,7 @@ export class Controller implements ControllerCallContext { async getRouter() { const controllerId = this.constructor.prototype.controllerId; + const { Router} = await import('express'); const router = Router(); for (const key in Controller.routes) { @@ -261,7 +264,16 @@ export class Controller implements ControllerCallContext { } } - const retVal = await bound(...args); + let retVal; + + if (process.env.ZIPKIN_URL) { + const spanName = req.originalUrl + '.' + route.methodFunc; + await instrumentAndWrap(spanName, req, res, async () => { + retVal = await bound(...args); + }); + } else { + retVal = await bound(...args); + } if ('stream' === route.responseObjectType) { return; diff --git a/src/containers/server/routes/FolderController.ts b/src/containers/server/routes/FolderController.ts index 4bf4066d..7ec78024 100644 --- a/src/containers/server/routes/FolderController.ts +++ b/src/containers/server/routes/FolderController.ts @@ -8,7 +8,7 @@ import { import {MimeTypes} from '../../../model/GoogleFile'; import {AuthConfig} from '../../../model/AccountJson'; import {FileContentService} from '../../../utils/FileContentService'; -import express from 'express'; +import type * as express from 'express'; import {TreeItem} from '../../../model/TreeItem'; import {UserConfigService} from '../../google_folder/UserConfigService'; import {DirectoryScanner, isTextFileName} from '../../transform/DirectoryScanner'; diff --git a/src/containers/server/routes/LogsController.ts b/src/containers/server/routes/LogsController.ts index d7a522da..0e8b5772 100644 --- a/src/containers/server/routes/LogsController.ts +++ b/src/containers/server/routes/LogsController.ts @@ -1,5 +1,5 @@ -import {Controller, RouteGet, RouteParamPath, RouteParamQuery} from './Controller'; -import {Logger, QueryOptions} from 'winston'; +import {Controller, RouteGet, RouteParamPath, RouteParamQuery} from './Controller.ts'; +import {Logger} from 'winston'; export class LogsController extends Controller { @@ -12,7 +12,8 @@ export class LogsController extends Controller { @RouteParamQuery('from') from?: number, @RouteParamQuery('until') until?: number, @RouteParamQuery('jobId') jobId?: string, - @RouteParamQuery('order') order?: 'desc' | 'asc' + @RouteParamQuery('order') order?: 'desc' | 'asc', + @RouteParamQuery('offset') offset?: number ) { if (!until && !from) { @@ -44,10 +45,10 @@ export class LogsController extends Controller { })); if (jobId) { - return results['jobLogFile']; + return results['jobLogFile'].slice(offset || 0); } - return results['dailyRotateFile'].reverse(); + return results['dailyRotateFile'].reverse().slice(offset || 0); } } diff --git a/src/containers/server/routes/PreviewController.ts b/src/containers/server/routes/PreviewController.ts index fdbe6cba..62d0e71a 100644 --- a/src/containers/server/routes/PreviewController.ts +++ b/src/containers/server/routes/PreviewController.ts @@ -42,8 +42,9 @@ export class PreviewController extends Controller { return; } - const ext = await this.fileSystem.guessExtension(filePath); - const mimeType = extToMime[ext]; + const ext = filePath.substring(filePath.lastIndexOf('.') + 1); + const guessedExt = await this.fileSystem.guessExtension(filePath); + const mimeType = extToMime[ext] || extToMime[guessedExt]; if (mimeType) { this.res.setHeader('Content-type', mimeType); diff --git a/src/containers/server/static.ts b/src/containers/server/static.ts index db948bda..ed162a9e 100644 --- a/src/containers/server/static.ts +++ b/src/containers/server/static.ts @@ -1,6 +1,6 @@ import path from 'path'; import fs from 'fs'; -import express from 'express'; +import type {Application, Request, Response, NextFunction} from 'express'; import {fileURLToPath} from 'url'; const __filename = fileURLToPath(import.meta.url); @@ -8,7 +8,7 @@ const __dirname = path.dirname(__filename); const HTML_DIR = __dirname + '/../../../apps/ui'; const MAIN_DIR = __dirname + '/../../..'; -export async function handleStaticHtml(app: express.Application, reqPath: string, url: string) { +export async function handleStaticHtml(app: Application, reqPath: string, url: string) { const hugoPath = path.resolve(MAIN_DIR, 'dist', 'hugo', (reqPath.substring(1) || 'index.html')); const generatedHtmlPath = path.resolve(MAIN_DIR, 'dist', 'hugo', 'ui', 'index.html'); const distPath = path.resolve(HTML_DIR, 'dist'); @@ -47,8 +47,8 @@ export async function handleStaticHtml(app: express.Application, reqPath: string return null; } -export async function initStaticDistPages(app: express.Application) { - app.use(async (req: express.Request, res: express.Response, next: express.NextFunction) => { +export async function initStaticDistPages(app: Application) { + app.use(async (req: Request, res: Response, next: NextFunction) => { const indexHtml = await handleStaticHtml(app, req.path, req.originalUrl); if (indexHtml) { res.status(200).header('Content-type', 'text/html').end(indexHtml); diff --git a/src/containers/server/vuejs.ts b/src/containers/server/vuejs.ts index 87d6202b..32f1df72 100644 --- a/src/containers/server/vuejs.ts +++ b/src/containers/server/vuejs.ts @@ -2,14 +2,14 @@ import {Logger} from 'vite'; import * as vite from 'vite'; import {fileURLToPath} from 'url'; import path from 'path'; -import express from 'express'; +import type {Application} from 'express'; import winston from 'winston'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const HTML_DIR = __dirname + '/../../../apps/ui'; -export async function initUiServer(app: express.Application, logger: winston.Logger) { +export async function initUiServer(app: Application, logger: winston.Logger) { const customLogger: Logger = { hasWarned: false, // eslint-disable-next-line @typescript-eslint/no-empty-function diff --git a/src/containers/transform/LocalLog.ts b/src/containers/transform/LocalLog.ts index 8fd178cc..7e461197 100644 --- a/src/containers/transform/LocalLog.ts +++ b/src/containers/transform/LocalLog.ts @@ -73,6 +73,16 @@ export class LocalLog { return null; } + findLastFileByPath(filePath: string) { + for (let rowNo = this.rows.length - 1; rowNo >= 0; rowNo--) { + const row = this.rows[rowNo]; + if (row.filePath === filePath) { + return row; + } + } + return null; + } + async remove(filePath: string): Promise { const originalLength = this.rows.length; this.rows = this.rows.filter(logRow => logRow.filePath !== filePath); @@ -91,4 +101,5 @@ export class LocalLog { return Object.values(lastOnes).filter(item => item.event !== 'removed'); } + } diff --git a/src/containers/transform/TaskLocalFileTransform.ts b/src/containers/transform/TaskLocalFileTransform.ts index 92914808..2c695e34 100644 --- a/src/containers/transform/TaskLocalFileTransform.ts +++ b/src/containers/transform/TaskLocalFileTransform.ts @@ -1,19 +1,20 @@ -import {QueueTask} from '../google_folder/QueueTask'; import winston from 'winston'; -import {FileContentService} from '../../utils/FileContentService'; -import {GoogleFile, MimeTypes} from '../../model/GoogleFile'; -import {BinaryFile, DrawingFile, LocalFile, MdFile} from '../../model/LocalFile'; -import {SvgTransform} from '../../SvgTransform'; -import {generateDocumentFrontMatter} from './frontmatters/generateDocumentFrontMatter'; -import {generateConflictMarkdown} from './frontmatters/generateConflictMarkdown'; -import {OdtProcessor} from '../../odt/OdtProcessor'; -import {UnMarshaller} from '../../odt/UnMarshaller'; -import {DocumentStyles, LIBREOFFICE_CLASSES} from '../../odt/LibreOffice'; -import {OdtToMarkdown} from '../../odt/OdtToMarkdown'; -import {LocalLinks} from './LocalLinks'; -import {SINGLE_THREADED_TRANSFORM} from './QueueTransformer'; -import {JobManagerContainer} from '../job/JobManagerContainer'; -import {UserConfig} from '../google_folder/UserConfigService'; + +import {QueueTask} from '../google_folder/QueueTask.ts'; +import {FileContentService} from '../../utils/FileContentService.ts'; +import {GoogleFile, MimeTypes} from '../../model/GoogleFile.ts'; +import {BinaryFile, DrawingFile, LocalFile, MdFile} from '../../model/LocalFile.ts'; +import {SvgTransform} from '../../SvgTransform.ts'; +import {generateDocumentFrontMatter} from './frontmatters/generateDocumentFrontMatter.ts'; +import {generateConflictMarkdown} from './frontmatters/generateConflictMarkdown.ts'; +import {OdtProcessor} from '../../odt/OdtProcessor.ts'; +import {UnMarshaller} from '../../odt/UnMarshaller.ts'; +import {DocumentStyles, LIBREOFFICE_CLASSES} from '../../odt/LibreOffice.ts'; +import {OdtToMarkdown} from '../../odt/OdtToMarkdown.ts'; +import {LocalLinks} from './LocalLinks.ts'; +import {SINGLE_THREADED_TRANSFORM} from './QueueTransformer.ts'; +import {JobManagerContainer} from '../job/JobManagerContainer.ts'; +import {UserConfig} from '../google_folder/UserConfigService.ts'; export function googleMimeToExt(mimeType: string, fileName: string) { switch (mimeType) { @@ -129,14 +130,19 @@ export class TaskLocalFileTransform extends QueueTask { let links = []; let errors = []; - const processor = new OdtProcessor(this.googleFolder, localFile.id, true); - await processor.load(); - await processor.unzipAssets(this.destinationDirectory, this.realFileName); - const content = processor.getContentXml(); - const stylesXml = processor.getStylesXml(); - const fileNameMap = processor.getFileNameMap(); + const odtPath = this.googleFolder.getRealPath() + '/' + localFile.id + '.odt'; + const destinationPath = this.destinationDirectory.getRealPath(); + + const rewriteRules = this.userConfig.rewrite_rules || []; if (SINGLE_THREADED_TRANSFORM) { + const processor = new OdtProcessor(odtPath, true); + await processor.load(); + await processor.unzipAssets(destinationPath, this.realFileName); + const content = processor.getContentXml(); + const stylesXml = processor.getStylesXml(); + const fileNameMap = processor.getFileNameMap(); + const parser = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentContent'); const document = parser.unmarshal(content); @@ -147,6 +153,7 @@ export class TaskLocalFileTransform extends QueueTask { } const converter = new OdtToMarkdown(document, styles, fileNameMap); + converter.setRewriteRules(rewriteRules); if (this.realFileName === '_index.md') { converter.setPicturesDir('./' + this.realFileName.replace(/.md$/, '.assets/')); } else { @@ -168,9 +175,9 @@ export class TaskLocalFileTransform extends QueueTask { const workerResult: WorkerResult = await this.jobManagerContainer.scheduleWorker('OdtToMarkdown', { localFile, realFileName: this.realFileName, - fileNameMap, - content, - stylesXml, + odtPath, + destinationPath, + rewriteRules, fm_without_version: this.userConfig.fm_without_version }); @@ -189,9 +196,6 @@ export class TaskLocalFileTransform extends QueueTask { } await this.destinationDirectory.writeFile(this.realFileName, frontMatter + markdown); - if (process.env.VERSION === 'dev') { - await this.destinationDirectory.writeFile(this.realFileName.replace(/.md$/, '.debug.xml'), content); - } this.localLinks.append(localFile.id, localFile.fileName, links); } diff --git a/src/containers/transform/TransformContainer.ts b/src/containers/transform/TransformContainer.ts index 7feb77f3..ee396c7b 100644 --- a/src/containers/transform/TransformContainer.ts +++ b/src/containers/transform/TransformContainer.ts @@ -240,7 +240,6 @@ export class TransformContainer extends Container { const destinationScanner = new DirectoryScanner(); const destinationFiles = await destinationScanner.scan(destinationDirectory); await addBinaryMetaData(destinationFiles, destinationDirectory); - await this.removeOutdatedLogEntries(destinationDirectory, destinationFiles); const localFilesGenerator = new LocalFilesGenerator(); const filesToGenerate: LocalFile[] = await localFilesGenerator.generateLocalFiles(googleFolderFiles); @@ -479,6 +478,11 @@ export class TransformContainer extends Container { continue; } + const lastLogRedir = this.localLog.findLastFileByPath(dirName ? dirName + '/' + fileName : fileName); + if (lastLogRedir?.event === 'removed') { + continue; + } + const redirFile: RedirFile = { type: 'redir', fileName, @@ -528,7 +532,8 @@ export class TransformContainer extends Container { const navigationFile = googleFiles.find(googleFile => googleFile.name === '.navigation' || googleFile.name === 'navigation'); if (navigationFile) { - const processor = new OdtProcessor(this.filesService, navigationFile.id); + const odtPath = this.filesService.getRealPath() + '/' + navigationFile.id + '.odt'; + const processor = new OdtProcessor(odtPath); await processor.load(); const content = processor.getContentXml(); const parser = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentContent'); diff --git a/src/google/GoogleDriveService.ts b/src/google/GoogleDriveService.ts index cecdad5b..951de7d6 100644 --- a/src/google/GoogleDriveService.ts +++ b/src/google/GoogleDriveService.ts @@ -126,7 +126,7 @@ export class GoogleDriveService { q: query, pageToken: pageToken, pageSize: 1000, - fields: 'nextPageToken, files(id, name, mimeType, modifiedTime, size, md5Checksum, lastModifyingUser, version, exportLinks, trashed, parents)', + fields: 'nextPageToken, files(id, name, mimeType, modifiedTime, size, md5Checksum, lastModifyingUser, version, exportLinks, trashed, parents, md5Checksum)', // fields: 'nextPageToken, files(*)', includeItemsFromAllDrives: true, supportsAllDrives: true, @@ -348,10 +348,17 @@ export class GoogleDriveService { formData.append('Metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json; charset=UTF-8' }) ); formData.append('Media', new Blob([buffer], { type: mimeType }), name); - return await driveFetchMultipart(this.quotaLimiter, accessToken, 'POST', url, { - uploadType: 'multipart', - supportsAllDrives: true - }, formData); + try { + return await driveFetchMultipart(this.quotaLimiter, accessToken, 'POST', url, { + uploadType: 'multipart', + supportsAllDrives: true + }, formData); + } catch (err) { + if (409 === parseInt(err.status)) { + this.logger.error(`Conflict on uploading: ${id} ${name}`); + } + throw err; + } } async update(accessToken: string, folderId: FileId, name: string, mimeType: string, buffer: Buffer, fileId: FileId) { diff --git a/src/google/driveFetch.ts b/src/google/driveFetch.ts index f51733ca..1184d966 100644 --- a/src/google/driveFetch.ts +++ b/src/google/driveFetch.ts @@ -2,6 +2,7 @@ import {Readable} from 'stream'; import {SimpleFile} from '../model/GoogleFile'; import opentelemetry from '@opentelemetry/api'; import {QuotaLimiter} from './QuotaLimiter'; +import {instrumentFunction} from '../telemetry'; async function handleReadable(obj): Promise { if (obj instanceof Readable) { @@ -141,7 +142,8 @@ async function driveRequest(quotaLimiter: QuotaLimiter, accessToken: string, met } if (!quotaLimiter) { - const response = await fetch(url, { + const fetchInstrumented = instrumentFunction(fetch, 1); + const response = await fetchInstrumented(url, { method, headers: { Authorization: 'Bearer ' + accessToken, @@ -161,7 +163,8 @@ async function driveRequest(quotaLimiter: QuotaLimiter, accessToken: string, met return await new Promise(async (resolve, reject) => { /* eslint-disable-line no-async-promise-executor */ const job = async () => { try { - const response = await fetch(url, { + const fetchInstrumented = instrumentFunction(fetch, 1); + const response = await fetchInstrumented(url, { method, headers: { Authorization: 'Bearer ' + accessToken, diff --git a/src/odt/MarkdownChunks.ts b/src/odt/MarkdownChunks.ts index 1d416e5b..a5853a77 100644 --- a/src/odt/MarkdownChunks.ts +++ b/src/odt/MarkdownChunks.ts @@ -1,5 +1,6 @@ -import {ListStyle, Style, TextProperty} from './LibreOffice'; -import {inchesToMm, inchesToPixels} from './utils'; +import {ListStyle, Style, TextProperty} from './LibreOffice.ts'; +import {inchesToPixels} from './utils.ts'; +import {applyRewriteRule, RewriteRule} from './applyRewriteRule.ts'; export type OutputMode = 'md' | 'html' | 'raw'; @@ -56,6 +57,7 @@ export interface MarkdownTagChunk { type MarkdownChunk = MarkdownTextChunk | MarkdownTagChunk; +// eslint-disable-next-line @typescript-eslint/no-unused-vars function debugChunkToText(chunk: MarkdownChunk) { if (chunk.isTag === false) { return chunk.text; @@ -312,6 +314,80 @@ function chunkToText(chunk: MarkdownChunk) { } + +function chunksToText(chunks: MarkdownChunk[], rules: RewriteRule[]) { + const retVal = []; + + for (let chunkNo = 0; chunkNo < chunks.length; chunkNo++) { + const chunk = chunks[chunkNo]; + + if ('tag' in chunk && ['SVG/', 'IMG/'].includes(chunk.tag)) { + let broke = false; + for (const rule of rules) { + const { shouldBreak, text } = applyRewriteRule(rule, { + ...chunk, + href: 'payload' in chunk ? chunk.payload?.href : undefined, + alt: 'payload' in chunk ? chunk.payload?.alt : undefined + }); + + if (shouldBreak) { + retVal.push(text); + broke = true; + break; + } + } + + if (broke) { + continue; + } + } + + if ('tag' in chunk && 'A' === chunk.tag) { + let matchingNo = -1; + + for (let idx = chunkNo + 1; idx < chunks.length; idx++) { + const chunkEnd = chunks[idx]; + if ('tag' in chunkEnd && chunkEnd.tag === '/A') { + matchingNo = idx; + break; + } + } + + if (matchingNo !== -1) { + const alt = chunksToText(chunks.slice(chunkNo + 1, matchingNo).filter(i => !i.isTag), rules).join(''); + let broke = false; + for (const rule of rules) { + const { shouldBreak, text } = applyRewriteRule(rule, { + ...chunk, + href: 'payload' in chunk ? chunk.payload?.href : undefined, + alt + }); + + if (shouldBreak) { + retVal.push(text); + broke = true; + break; + } + } + + if (broke) { + chunks.splice(chunkNo, matchingNo - chunkNo); + continue; + } + } + } + + retVal.push(chunkToText(chunk)); + } + + // chunks.map(c => chunkToText(c)); +/* +*/ + + return retVal; +} + + export class MarkdownChunks { chunks: MarkdownChunk[] = []; @@ -323,13 +399,13 @@ export class MarkdownChunks { this.chunks.push(s); } - toString() { + toString(rules: RewriteRule[] = []) { // console.log(this.chunks.map(c => debugChunkToText(c)).join('\n')); - return this.chunks.map(c => chunkToText(c)).join(''); + return chunksToText(this.chunks, rules).join(''); } - extractText(start: number, end: number) { - const slice = this.chunks.slice(start, end).filter(i => !i.isTag).map(c => chunkToText(c)).join(''); + extractText(start: number, end: number, rules: RewriteRule[] = []) { + const slice = chunksToText(this.chunks.slice(start, end).filter(i => !i.isTag), rules).join(''); return slice; } diff --git a/src/odt/OdtProcessor.ts b/src/odt/OdtProcessor.ts index 6fdb031b..07c19334 100644 --- a/src/odt/OdtProcessor.ts +++ b/src/odt/OdtProcessor.ts @@ -1,4 +1,5 @@ -import {FileContentService} from '../utils/FileContentService'; +import fs from 'fs'; +import path from 'path'; import JSZip from 'jszip'; import crypto from 'crypto'; @@ -11,23 +12,21 @@ function getExt(fileName) { } export class OdtProcessor { - private readonly fileName: string; private contentXml: string; private stylesXml: string; private files: { [p: string]: JSZip.JSZipObject }; private fileNameMap: { [name: string]: string }; - constructor(private fileSystem: FileContentService, private fileId: string, private contentAddressable = false) { - this.fileName = fileId + '.odt'; + constructor(private odtPath: string, private contentAddressable = false) { this.fileNameMap = {}; } async load() { - if (!await this.fileSystem.exists(this.fileName)) { + if (!fs.existsSync(this.odtPath)) { return; } const jsZip = new JSZip(); - const input = await this.fileSystem.readBuffer(this.fileName); + const input: Buffer = fs.readFileSync(this.odtPath); const zip = await jsZip.loadAsync(input); this.files = zip.folder('').files; @@ -40,9 +39,13 @@ export class OdtProcessor { } } - async unzipAssets(destinationDirectory: FileContentService, destinationName: string) { - const assetsDirectory = await destinationDirectory.getSubFileService(destinationName.replace(/.md$/, '.assets')); - await assetsDirectory.mkdir(''); + async unzipAssets(destinationPath: string, destinationName: string) { + const assetsDirectory = path.join(destinationPath, destinationName.replace(/.md$/, '.assets')); + + if (!fs.existsSync(assetsDirectory)) { + fs.mkdirSync(assetsDirectory, { recursive: true }); + } + const written = []; for (const relativePath in this.files) { if (!relativePath.endsWith('.png') && !relativePath.endsWith('.jpg')) { @@ -66,13 +69,13 @@ export class OdtProcessor { this.fileNameMap[fileName] = fileName; } written.push(this.fileNameMap[fileName]); - await assetsDirectory.writeBuffer(this.fileNameMap[fileName], buffer); + fs.writeFileSync(path.join(assetsDirectory, this.fileNameMap[fileName]), buffer); } - const files = await assetsDirectory.list(''); + const files = fs.readdirSync(assetsDirectory); for (const file of files) { if (written.indexOf(file) === -1) { - await assetsDirectory.remove(file); + fs.unlinkSync(path.join(assetsDirectory, file)); } } } diff --git a/src/odt/OdtToMarkdown.ts b/src/odt/OdtToMarkdown.ts index 09b6b465..d1431370 100644 --- a/src/odt/OdtToMarkdown.ts +++ b/src/odt/OdtToMarkdown.ts @@ -15,13 +15,14 @@ import { TextProperty, TextSpace, TextSpan -} from './LibreOffice'; -import {urlToFolderId} from '../utils/idParsers'; -import {MarkdownChunks} from './MarkdownChunks'; -import {isMarkdownMacro, StateMachine} from './StateMachine'; -import {inchesToPixels, inchesToSpaces, spaces} from './utils'; -import {extractPath} from './extractPath'; -import {mergeDeep} from './mergeDeep'; +} from './LibreOffice.ts'; +import {urlToFolderId} from '../utils/idParsers.ts'; +import {MarkdownChunks} from './MarkdownChunks.ts'; +import {isMarkdownMacro, StateMachine} from './StateMachine.ts'; +import {inchesToPixels, inchesToSpaces, spaces} from './utils.ts'; +import {extractPath} from './extractPath.ts'; +import {mergeDeep} from './mergeDeep.ts'; +import {RewriteRule} from './applyRewriteRule.ts'; function getBaseFileName(fileName) { return fileName.replace(/.*\//, ''); @@ -62,6 +63,7 @@ export class OdtToMarkdown { public readonly links: Set = new Set(); private readonly chunks: MarkdownChunks = new MarkdownChunks(); private picturesDir = ''; + private rewriteRules: RewriteRule[] = []; constructor(private document: DocumentContent, private documentStyles: DocumentStyles, private fileNameMap: FileNameMap = {}) { this.stateMachine = new StateMachine(this.chunks); @@ -115,7 +117,7 @@ export class OdtToMarkdown { this.stateMachine.postProcess(); - const markdown = this.chunks.toString(); + const markdown = this.chunks.toString(this.rewriteRules); const trimmed = this.trimBreaks(markdown); return await this.rewriteHeaders(trimmed); } @@ -326,7 +328,7 @@ export class OdtToMarkdown { async drawGToText(drawG: DrawG) { this.stateMachine.pushTag('HTML_MODE/'); - const style = this.getStyle(drawG.styleName); + this.getStyle(drawG.styleName); let maxx = 0; let maxy = 0; @@ -682,4 +684,9 @@ export class OdtToMarkdown { setPicturesDir(picturesDir: string) { this.picturesDir = picturesDir; } + + setRewriteRules(rewriteRules: RewriteRule[]) { + this.rewriteRules = rewriteRules; + this.stateMachine.setRewriteRules(rewriteRules); + } } diff --git a/src/odt/StateMachine.ts b/src/odt/StateMachine.ts index 52504adf..7ef41fce 100644 --- a/src/odt/StateMachine.ts +++ b/src/odt/StateMachine.ts @@ -1,7 +1,9 @@ -import {isClosing, isOpening, MarkdownChunks, OutputMode, TAG, TagPayload} from './MarkdownChunks'; -import {fixCharacters, spaces} from './utils'; import slugify from 'slugify'; +import {isClosing, isOpening, MarkdownChunks, OutputMode, TAG, TagPayload} from './MarkdownChunks.ts'; +import {fixCharacters, spaces} from './utils.ts'; +import {RewriteRule} from './applyRewriteRule.ts'; + interface TagLeaf { mode: OutputMode; level: number; @@ -66,6 +68,7 @@ export class StateMachine { public errors: string[] = []; private readonly tagsTree: TagLeaf[] = []; private listLevel = 0; + private rewriteRules: RewriteRule[] = []; currentMode: OutputMode = 'md'; headersMap: { [id: string]: string } = {}; @@ -280,7 +283,7 @@ export class StateMachine { } if (tag === '/I') { - const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position); + const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position, this.rewriteRules); if (innerTxt.startsWith('{{%') && innerTxt.endsWith('%}}')) { this.markdownChunks.removeChunk(payload.position); this.markdownChunks.removeChunk(this.currentLevel.payload.position); @@ -295,7 +298,7 @@ export class StateMachine { } if (tag === '/P' || tag === '/PRE') { - const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position); + const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position, this.rewriteRules); switch (this.currentMode) { case 'raw': { @@ -333,7 +336,7 @@ export class StateMachine { } if (tag === '/CODE') { - const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position); + const innerTxt = this.markdownChunks.extractText(this.currentLevel.payload.position, payload.position, this.rewriteRules); switch (this.currentMode) { case 'md': if (isMarkdownMacro(innerTxt)) { @@ -511,9 +514,7 @@ export class StateMachine { for (let position = this.markdownChunks.length - 1; position >= 0; position--) { const chunk = this.markdownChunks.chunks[position]; if (chunk.isTag && chunk.tag === 'P') { - const origNum = chunk.payload?.number; if (nextPara) { - const origNextNum = nextPara.payload?.number; if (nextPara.payload?.listLevel && !chunk.payload?.listLevel) { chunk.payload.listLevel = nextPara?.payload?.listLevel; } @@ -700,14 +701,14 @@ export class StateMachine { } if (nextParaClosing > 0) { - const innerText = this.markdownChunks.extractText(position, nextParaClosing); + const innerText = this.markdownChunks.extractText(position, nextParaClosing, this.rewriteRules); if (innerText.length === 0) { continue; } } if (previousParaPosition > 0) { - const innerText = this.markdownChunks.extractText(previousParaPosition, position); + const innerText = this.markdownChunks.extractText(previousParaPosition, position, this.rewriteRules); if (innerText.length === 0) { continue; } @@ -736,4 +737,8 @@ export class StateMachine { pushError(error: string) { this.errors.push(error); } + + setRewriteRules(rewriteRules: RewriteRule[]) { + this.rewriteRules = rewriteRules; + } } diff --git a/src/odt/applyRewriteRule.ts b/src/odt/applyRewriteRule.ts new file mode 100644 index 00000000..04627fb4 --- /dev/null +++ b/src/odt/applyRewriteRule.ts @@ -0,0 +1,54 @@ +import path from 'path'; + +export interface RewriteRule { + tag?: string; + match: string; + replace?: string; + template: string; +} + +export interface Chunk { + mode: string; + tag?: string; + href: string; + alt?: string; +} + +export function applyRewriteRule(rule: RewriteRule, chunk: Chunk) { + const href = chunk.href || ''; + const basename = path.basename(href); + const alt = chunk.alt || ''; + const chunkTag = chunk.tag || ''; + + if (rule.tag && chunkTag.replaceAll('/', '') !== rule.tag.replaceAll('/', '')) { + return { shouldBreak: false }; + } + + if (rule.match && rule.match === '$alt') { + if (href !== alt) { + return { shouldBreak: false }; + } + } else + if (rule.match) { + const matchRegExp = new RegExp(rule.match); + if (!matchRegExp.test(href)) { + return { shouldBreak: false }; + } + } + + let value = href; + + const replaceRegExp = rule.replace ? new RegExp(rule.replace) : undefined; + if (replaceRegExp) { + const arr = replaceRegExp.exec(value); + value = arr[1]; + } + + const text = rule.template + .replaceAll('$href', href) + .replaceAll('$basename', basename) + .replaceAll('$label', alt) + .replaceAll('$value', value); + + return { shouldBreak: true, text }; +} diff --git a/src/odt/executeOdtToMarkdown.ts b/src/odt/executeOdtToMarkdown.ts index 3863072a..d86f1cd9 100644 --- a/src/odt/executeOdtToMarkdown.ts +++ b/src/odt/executeOdtToMarkdown.ts @@ -2,18 +2,29 @@ import {OdtToMarkdown} from './OdtToMarkdown'; import {UnMarshaller} from './UnMarshaller'; import {DocumentStyles, LIBREOFFICE_CLASSES} from './LibreOffice'; import {generateDocumentFrontMatter} from '../containers/transform/frontmatters/generateDocumentFrontMatter'; +import {OdtProcessor} from './OdtProcessor'; +import fs from 'fs'; +import path from 'path'; export async function executeOdtToMarkdown(workerData) { + const processor = new OdtProcessor(workerData.odtPath, true); + await processor.load(); + await processor.unzipAssets(workerData.destinationPath, workerData.realFileName); + const content = processor.getContentXml(); + const stylesXml = processor.getStylesXml(); + const fileNameMap = processor.getFileNameMap(); + const parser = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentContent'); - const document = parser.unmarshal(workerData.content); + const document = parser.unmarshal(content); const parserStyles = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentStyles'); - const styles: DocumentStyles = parserStyles.unmarshal(workerData.stylesXml); + const styles: DocumentStyles = parserStyles.unmarshal(stylesXml); if (!styles) { throw Error('No styles unmarshalled'); } - const converter = new OdtToMarkdown(document, styles, workerData.fileNameMap); + const converter = new OdtToMarkdown(document, styles, fileNameMap); + converter.setRewriteRules(workerData.rewriteRules); if (workerData.realFileName === '_index.md') { converter.setPicturesDir('./' + workerData.realFileName.replace(/.md$/, '.assets/')); } else { @@ -24,5 +35,10 @@ export async function executeOdtToMarkdown(workerData) { const frontMatter = generateDocumentFrontMatter(workerData.localFile, links, workerData.fm_without_version); const errors = converter.getErrors(); + + if (process.env.VERSION === 'dev') { + fs.writeFileSync(path.join(workerData.destinationPath, workerData.realFileName.replace(/.md$/, '.debug.xml')), markdown); + } + return { links, frontMatter, markdown, errors }; } diff --git a/src/telemetry.ts b/src/telemetry.ts index 9ce1f1a2..24aa1452 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -2,7 +2,6 @@ import opentelemetry, {Span, SpanKind} from '@opentelemetry/api'; import {ZipkinExporter} from '@opentelemetry/exporter-zipkin'; import {InstrumentationBase, registerInstrumentations} from '@opentelemetry/instrumentation'; import {HttpInstrumentation} from '@opentelemetry/instrumentation-http'; -import {ExpressInstrumentation} from '@opentelemetry/instrumentation-express'; import {Resource} from '@opentelemetry/resources'; import {NodeTracerProvider} from '@opentelemetry/sdk-trace-node'; import {AlwaysOnSampler, SimpleSpanProcessor} from '@opentelemetry/sdk-trace-base'; @@ -56,6 +55,36 @@ export function TelemetryMethodDisable() { }; } +export async function instrumentAndWrap(spanName, req, res, func) { + const tracer = opentelemetry.trace.getTracer( + provider.resource.attributes[SemanticResourceAttributes.SERVICE_NAME].toString(), + '1.0' + ); + + const traceparent = req.header('traceparent'); + + const input = { traceparent }; + const activeContext = opentelemetry.propagation.extract(opentelemetry.context.active(), input); + + return tracer.startActiveSpan( + spanName, + { kind: SpanKind.SERVER }, + activeContext, + async (span) => { + try { + const traceId = span.spanContext().traceId; + res.header('trace-id', traceId); + return await func(); + } catch (err) { + // err.stack = [err.message].concat(stackTrace).join('\n'); + span.recordException(err); + throw err; + } finally { + span.end(); + } + }); +} + export class ClassInstrumentation extends InstrumentationBase { private className: string; @@ -102,14 +131,60 @@ export class ClassInstrumentation extends InstrumentationBase { spanName += ')'; } - const span = tracer.startSpan(spanName, { kind: SpanKind.INTERNAL }); + return tracer.startActiveSpan( + spanName, + { kind: SpanKind.INTERNAL }, + async (span) => { + try { + const branch = 'develop'; + const url = `https://github.com/mieweb/wikiGDrive/blob/${branch}/src${instrumentation.path}`; + span.setAttribute('src', url); - try { - const branch = 'develop'; - const url = `https://github.com/mieweb/wikiGDrive/blob/${branch}/src${instrumentation.path}`; - span.setAttribute('src', url); + return await origMethod.apply(this, args); + } catch (err) { + err.stack = [err.message].concat(stackTrace).join('\n'); + span.recordException(err); + throw err; + } finally { + span.end(); + } + }); + }; + this.classPrototype[methodName].origMethod = origMethod; + } + } +} + +export function instrumentFunction(func, telemetryParamCount = 0, telemetryParamOffset = 0) { + return async function (...args) { + if (!process.env.ZIPKIN_URL) { + return await func(...args); + } + + const stackTrace = new Error().stack.split('\n').splice(2); + const tracer = opentelemetry.trace.getTracer( + provider.resource.attributes[SemanticResourceAttributes.SERVICE_NAME].toString(), + '1.0' + ); + + let spanName = func.name; + if (telemetryParamCount) { + spanName += '('; + for (let i = telemetryParamOffset; i < telemetryParamCount + telemetryParamOffset; i++) { + if (i > 0) { + spanName += ', '; + } + spanName += args[0]; + } + spanName += ')'; + } - return await origMethod.apply(this, args); + return tracer.startActiveSpan( + spanName, + { kind: SpanKind.INTERNAL }, + async (span) => { + try { + return await func(...args); } catch (err) { err.stack = [err.message].concat(stackTrace).join('\n'); span.recordException(err); @@ -117,11 +192,8 @@ export class ClassInstrumentation extends InstrumentationBase { } finally { span.end(); } - - }; - this.classPrototype[methodName].origMethod = origMethod; - } - } + }); + }; } export async function addTelemetry(serviceName: string, mainDir: string) { @@ -156,8 +228,7 @@ export async function addTelemetry(serviceName: string, mainDir: string) { span.updateName('http_server ' + request.method + ' ' + request['originalUrl'].replace(/\?.*/, '')); } }, - }), - new ExpressInstrumentation() + }) ], }); @@ -172,7 +243,6 @@ export async function addTelemetry(serviceName: string, mainDir: string) { ] }); - provider.addSpanProcessor( new SimpleSpanProcessor( new ZipkinExporter({ diff --git a/src/wikigdrive.sh b/src/wikigdrive.sh index 3388fe7e..b6ba96a3 100755 --- a/src/wikigdrive.sh +++ b/src/wikigdrive.sh @@ -44,7 +44,7 @@ if [[ ! -f "$MAIN_DIR/src/cli/wikigdrive-$CMD.ts" ]]; then fi if test "$INSPECT" = "--inspect"; then - /usr/bin/env node --inspect --no-warnings --experimental-specifier-resolution=node --loader $NODE_MODULES/ts-node/esm $MAIN_DIR/src/cli/wikigdrive-$CMD.ts $ORIG_ARGS + /usr/bin/env node --inspect --no-warnings --experimental-specifier-resolution=node --loader ts-node/esm $MAIN_DIR/src/cli/wikigdrive-$CMD.ts $ORIG_ARGS else - /usr/bin/env node --no-warnings --experimental-specifier-resolution=node --loader $NODE_MODULES/ts-node/esm $MAIN_DIR/src/cli/wikigdrive-$CMD.ts $ORIG_ARGS + /usr/bin/env node --no-warnings --experimental-specifier-resolution=node --loader ts-node/esm $MAIN_DIR/src/cli/wikigdrive-$CMD.ts $ORIG_ARGS fi diff --git a/src/wikigdrivectl.sh b/src/wikigdrivectl.sh index 1e958134..7de94b12 100755 --- a/src/wikigdrivectl.sh +++ b/src/wikigdrivectl.sh @@ -46,7 +46,7 @@ if [[ ! -f "$MAIN_DIR/src/cli/wikigdrivectl-$CMD.ts" ]]; then fi if test "$INSPECT" = "--inspect"; then - /usr/bin/env node --inspect --no-warnings --experimental-specifier-resolution=node --loader $NODE_MODULES/ts-node/esm $MAIN_DIR/src/cli/wikigdrivectl-$CMD.ts $ORIG_ARGS + /usr/bin/env node --inspect --no-warnings --experimental-specifier-resolution=node --loader ts-node/esm $MAIN_DIR/src/cli/wikigdrivectl-$CMD.ts $ORIG_ARGS else - /usr/bin/env node --no-warnings --experimental-specifier-resolution=node --loader $NODE_MODULES/ts-node/esm $MAIN_DIR/src/cli/wikigdrivectl-$CMD.ts $ORIG_ARGS + /usr/bin/env node --no-warnings --experimental-specifier-resolution=node --loader ts-node/esm $MAIN_DIR/src/cli/wikigdrivectl-$CMD.ts $ORIG_ARGS fi diff --git a/test/odt/OdtLoad.test.ts b/test/odt/OdtLoad.test.ts index 078a9a72..c88ab509 100644 --- a/test/odt/OdtLoad.test.ts +++ b/test/odt/OdtLoad.test.ts @@ -14,7 +14,8 @@ const __dirname = path.dirname(__filename); describe('OdtLoad', () => { it('test content.xml transform to object', async () => { const fileSystem = new FileContentService(__dirname); - const processor = new OdtProcessor(fileSystem, 'example_document'); + const odtPath = fileSystem.getRealPath() + '/' + 'example_document.odt'; + const processor = new OdtProcessor(odtPath); await processor.load(); const content = processor.getContentXml(); diff --git a/test/odt_md/MarkDownTransform.test.ts b/test/odt_md/MarkDownTransform.test.ts index fe01b363..a978887a 100644 --- a/test/odt_md/MarkDownTransform.test.ts +++ b/test/odt_md/MarkDownTransform.test.ts @@ -1,12 +1,12 @@ import {assert} from 'chai'; import fs from 'fs'; -import {compareTexts} from '../utils'; -import {OdtToMarkdown} from '../../src/odt/OdtToMarkdown'; -import {DocumentContent, DocumentStyles, LIBREOFFICE_CLASSES} from '../../src/odt/LibreOffice'; -import {UnMarshaller} from '../../src/odt/UnMarshaller'; -import {OdtProcessor} from '../../src/odt/OdtProcessor'; -import {FileContentService} from '../../src/utils/FileContentService'; +import {compareTexts} from '../utils.ts'; +import {OdtToMarkdown} from '../../src/odt/OdtToMarkdown.ts'; +import {DocumentContent, DocumentStyles, LIBREOFFICE_CLASSES} from '../../src/odt/LibreOffice.ts'; +import {UnMarshaller} from '../../src/odt/UnMarshaller.ts'; +import {OdtProcessor} from '../../src/odt/OdtProcessor.ts'; +import {FileContentService} from '../../src/utils/FileContentService.ts'; import path from 'path'; import { fileURLToPath } from 'url'; @@ -129,7 +129,8 @@ describe('MarkDownTransformTest', () => { async function transformOdt(id: string) { const folder = new FileContentService(__dirname); - const processor = new OdtProcessor(folder, id); + const odtPath = folder.getRealPath() + '/' + id + '.odt'; + const processor = new OdtProcessor(odtPath); await processor.load(); if (!processor.getContentXml()) { throw Error('No odt processed'); diff --git a/test/odt_md/RewriteRules.test.ts b/test/odt_md/RewriteRules.test.ts new file mode 100644 index 00000000..6dea2745 --- /dev/null +++ b/test/odt_md/RewriteRules.test.ts @@ -0,0 +1,67 @@ +import {fileURLToPath} from 'url'; +import path from 'path'; +import fs from 'fs'; +import {assert} from 'chai'; +import {compareTexts} from '../utils.ts'; +import {FileContentService} from '../../src/utils/FileContentService.ts'; +import {OdtProcessor} from '../../src/odt/OdtProcessor.ts'; +import {UnMarshaller} from '../../src/odt/UnMarshaller.ts'; +import {DocumentContent, DocumentStyles, LIBREOFFICE_CLASSES} from '../../src/odt/LibreOffice.ts'; +import {OdtToMarkdown} from '../../src/odt/OdtToMarkdown.ts'; +import {RewriteRule} from '../../src/odt/applyRewriteRule.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const RULES: RewriteRule[] = [ + { + match: '(?:https?:\\/\\/)?(?:www\\.)?(?:youtube\\.com\\/(?:[^\\/\\n\\s]+\\/\\S+\\/|(?:v|e(?:mbed)?)\\/|\\S*?[?&]v=)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})', + replace: '(?:https?:\\/\\/)?(?:www\\.)?(?:youtube\\.com\\/(?:[^\\/\\n\\s]+\\/\\S+\\/|(?:v|e(?:mbed)?)\\/|\\S*?[?&]v=)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})', + template: '[$label](https://youtube.be/$value)' + }, + { + match: 'https://github.com/mieweb/docs_video/blob/main/', + template: '[https://cloudflare.com/$basename](https://cloudflare.com/$basename)' + }, + { + match: '.png$', + template: '' + } +]; + +describe('RewriteRulesTest', () => { + + it('test ./rewrite-rules.md.markdown', async () => { + const testMarkdown = fs.readFileSync(__dirname + '/rewrite-rules.md').toString(); + const markdown = await transformOdt('rewrite-rules'); + assert.ok(compareTexts(testMarkdown, markdown)); + }); + +}); + +async function transformOdt(id: string) { + const folder = new FileContentService(__dirname); + const odtPath = folder.getRealPath() + '/' + id + '.odt'; + const processor = new OdtProcessor(odtPath); + await processor.load(); + if (!processor.getContentXml()) { + throw Error('No odt processed'); + } + return transform(processor.getContentXml(), processor.getStylesXml()); +} + +async function transform(contentXml: string, stylesXml: string) { + const parser = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentContent'); + const document: DocumentContent = parser.unmarshal(contentXml); + if (!document) { + throw Error('No document unmarshalled'); + } + const parserStyles = new UnMarshaller(LIBREOFFICE_CLASSES, 'DocumentStyles'); + const styles: DocumentStyles = parserStyles.unmarshal(stylesXml); + if (!styles) { + throw Error('No styles unmarshalled'); + } + const converter = new OdtToMarkdown(document, styles); + converter.setRewriteRules(RULES); + return await converter.convert(); +} diff --git a/test/odt_md/rewrite-rules.md b/test/odt_md/rewrite-rules.md new file mode 100644 index 00000000..c5b52b8f --- /dev/null +++ b/test/odt_md/rewrite-rules.md @@ -0,0 +1,12 @@ +[Animation vs. Physics](https://youtube.be/ErMSHiQRnc8) + +[https://www.youtube.com/watch?v=ErMSHiQRnc8](https://youtube.be/ErMSHiQRnc8) + +How to show a player: + + + + +You + +[https://cloudflare.com/EH_Task%20list.mp4](https://cloudflare.com/EH_Task%20list.mp4) diff --git a/test/odt_md/rewrite-rules.odt b/test/odt_md/rewrite-rules.odt new file mode 100644 index 00000000..ff91f5e4 Binary files /dev/null and b/test/odt_md/rewrite-rules.odt differ diff --git a/tsconfig.json b/tsconfig.json index deb1a3c5..f8a14777 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,10 @@ { "compilerOptions": { - "lib": ["es2021", "dom"], - "module": "ESNext", - "moduleResolution": "node", - "target": "es2021", + "lib": ["es2022", "dom"], + "module": "node16", + "moduleResolution": "node16", + "target": "es2022", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "esModuleInterop": true, "sourceMap": true, @@ -15,9 +16,9 @@ "transpileOnly": true, "files": true, "compilerOptions": { - "module": "ESNext", + "module": "node16", "esModuleInterop": true, - "moduleResolution": "node" + "moduleResolution": "node16" } }, "exclude": [ diff --git a/website/_index.md b/website/_index.md index d0e989aa..426da708 100644 --- a/website/_index.md +++ b/website/_index.md @@ -15,7 +15,7 @@ WikiGDrive is a node app that uses the [Google Drive API](https://developers.goo [Google Drive Notes](https://docs.google.com/document/d/1H6vwfQXIexdg4ldfaoPUjhOZPnSkNn6h29WD6Fi-SBY/edit#) | [Github Project](https://github.com/mieweb/wikiGDrive/projects) -| [Github Developer Notes](docs/developer.md) +| [Github Developer Notes](docs/developer_guide.md) With a "Shared Drive" as the key, WikiGDrive: @@ -30,7 +30,7 @@ WikiGDrive scans for changes in the drive and then refresh the local converted f ## Developer Documentation -* [Developer README](docs/developer.md) +* [Developer README](docs/developer_guide.md) * [Internals](docs/internals.md) ## Install from NPM diff --git a/website/docs/_index.md b/website/docs/_index.md index 68e3e3bd..7b939729 100644 --- a/website/docs/_index.md +++ b/website/docs/_index.md @@ -1,5 +1,5 @@ --- -title: Introduction +title: _index navWeight: 1000 # Upper weight gets higher precedence, optional. --- # wikiGDrive @@ -16,23 +16,23 @@ WikiGDrive is a node app that uses the [Google Drive API](https://developers.goo [Google Drive Notes](https://docs.google.com/document/d/1H6vwfQXIexdg4ldfaoPUjhOZPnSkNn6h29WD6Fi-SBY/edit#) | [Github Project](https://github.com/mieweb/wikiGDrive/projects) -| [Github Developer Notes](docs/developer.md) +| [Github Developer Notes](./developer_guide.md) With a "Shared Drive" as the key, WikiGDrive: * Reads all the files from a Google "Shared Drive" * Builds a map of the driveId (URL) to the pathname in the "Shared Drive" * For each Google Document: - * Converts to a Markdown file with the path (instead of the driveId for the file) - * Changes driveId to the path (eg: 12lvdxKgGsD.../edit would be changed to /filename - * Support diagrams as SVG (and map the URLs in the diagram) + * Converts to a Markdown file with the path (instead of the driveId for the file) + * Changes driveId to the path (eg: 12lvdxKgGsD.../edit would be changed to /filename + * Support diagrams as SVG (and map the URLs in the diagram) WikiGDrive scans for changes in the drive and then refresh the local converted files. ## Developer Documentation -* [Developer README](docs/developer.md) -* [Internals](docs/internals.md) +* [Developer README](./developer_guide.md) +* [Internals](./internals.md) ## Usage and options diff --git a/website/docs/developer.md b/website/docs/developer_guide.md similarity index 79% rename from website/docs/developer.md rename to website/docs/developer_guide.md index 4ae9b372..4207a4df 100644 --- a/website/docs/developer.md +++ b/website/docs/developer_guide.md @@ -6,7 +6,7 @@ navWeight: -15 See [Node setup on the system](#Node-setup-on-the-system) for prereq. -[Example Google Drive Shared Folder](https://drive.google.com/drive/folders/0AIkOKXbzWCtSUk9PVA) +[Example Google Drive Shared Folder](https://drive.google.com/open?id=0AIkOKXbzWCtSUk9PVA) # Node setup on the system @@ -70,10 +70,10 @@ docker rm -f wikigdrive ## Authentication ### Client ID for the Web Application Add-On / Authentication -Link to production's OAUTH configuration: -https://console.cloud.google.com/apis/credentials/oauthclient/762352378313-3u5pagjnk24g9640a5j1bmlsvobtlq2k.apps.googleusercontent.com?project=wikigdrive -Stored in /home/githubactions/wikigdrive/env.prod +Link to production's OAUTH configuration: https://console.cloud.google.com/apis/credentials/oauthclient/762352378313-3u5pagjnk24g9640a5j1bmlsvobtlq2k.apps.googleusercontent.com?project=wikigdrive + +Stored in /home/wikigdrive/env.prod ### This is for the Service Account https://console.cloud.google.com/iam-admin/serviceaccounts/details/103184696095283927333?project=wikigdrive @@ -84,7 +84,7 @@ https://console.cloud.google.com/iam-admin/serviceaccounts/details/1031846960952 This is for configuring Google Apps and their Console to permit the Google Marketplace to the store. -See [app_script](../../apps/app-script) +See folder `/apps/app-script` in the sources ## Runner @@ -114,7 +114,7 @@ root@wgd-dev:~# docker exec -it wikigdrive-prod bash wikigdrive --service_account /service_account.json drives ``` -![Code Diagram](https://docs.google.com/drawings/d/e/2PACX-1vREcniLAig0DiPqSxu5QRqgiGHWL5INKfjMlqSvXK9vTbas3JqorzbuONLeTrNOD0MBPC7QB3Gd_NY7/pub?w=960&h=720) [src](https://docs.google.com/drawings/d/1LSveM3s_Fmi9411FW9Z-NA50fbNHHW2y_PQo3NSUPAI/edit) +![Code Diagram](https://docs.google.com/drawings/d/e/2PACX-1vREcniLAig0DiPqSxu5QRqgiGHWL5INKfjMlqSvXK9vTbas3JqorzbuONLeTrNOD0MBPC7QB3Gd_NY7/pub?w=960&h=720) [src](https://docs.google.com/drawings/d/1LSveM3s_Fmi9411FW9Z-NA50fbNHHW2y_PQo3NSUPAI/edit) Cool trick to watch changes as they happen in a document: @@ -137,7 +137,7 @@ docker run --name zipkin -d -p 9411:9411 --restart unless-stopped openzipkin/zip Set app env var to: ``` -ZIPKIN_URL=http://localhost:9411` +ZIPKIN_URL=http://localhost:9411 ``` ## Debugging @@ -148,12 +148,18 @@ ZIPKIN_URL=http://localhost:9411` Chrome - Go to `chrome://inspect` +``` +Go to `chrome://inspect` +``` Visual Studio Code 1.10+ - In the Debug panel, click the settings icon to open .vscode/launch.json. Select "Node.js" for initial setup. +``` +In the Debug panel, click the settings icon to open .vscode/launch.json. Select "Node.js" for initial setup. +``` JetBrains WebStorm and other JetBrains IDEs - Create a new Node.js debug configuration and hit Debug. --inspect will be used by default for Node.js 7+. To disable uncheck js.debugger.node.use.inspect in the IDE Registry. To learn more about running and debugging Node.js in WebStorm and other JetBrains IDEs, check out WebStorm online help. +``` +Create a new Node.js debug configuration and hit Debug. --inspect will be used by default for Node.js 7+. To disable uncheck js.debugger.node.use.inspect in the IDE Registry. To learn more about running and debugging Node.js in WebStorm and other JetBrains IDEs, check out WebStorm online help. +``` diff --git a/website/docs/install.md b/website/docs/install.md index 5307f376..fd6b4b04 100644 --- a/website/docs/install.md +++ b/website/docs/install.md @@ -1,5 +1,5 @@ --- -title: Installation Guide +title: Install navWeight: 990 # Upper weight gets higher precedence, optional. --- ## Install from NPM diff --git a/website/docs/internals.md b/website/docs/internals.md index 4692d8e2..a925e37d 100644 --- a/website/docs/internals.md +++ b/website/docs/internals.md @@ -11,7 +11,7 @@ navWeight: -15 * folders.json - a listing of each google shared folder * One folder for each drive - * Second folder with the same name with `_transform` on the end to hold markdown version + * Second folder with the same name with `_transform` on the end to hold markdown version * quota.json - google throttle for limited rate ``` @@ -81,12 +81,12 @@ navWeight: -15 ## Note this is going away. Will be replacing this single database with a multi-file version for scale. -- id - Google's fileId -- name - Title set inside google docs. It is not unique -- mimeType - Google's mime type or 'conflict' or 'redirect' -- modifiedTime - Server-size mtime -- localPath - real local path, unique with handled conflicts and redirects (in case of title rename) -- lastAuthor - Google's last author if available +* id - Google's fileId +* name - Title set inside google docs. It is not unique +* mimeType - Google's mime type or 'conflict' or 'redirect' +* modifiedTime - Server-size mtime +* localPath - real local path, unique with handled conflicts and redirects (in case of title rename) +* lastAuthor - Google's last author if available ``` { @@ -128,11 +128,11 @@ navWeight: -15 ### local_files.json is indexed with file id -- desiredLocalPath - slugified name. It is not unique, wikigdrive handles redirects so it is NOT real path in local system -- dirty - file needs to be downloaded -- conflicting - array of fileIds when mimeType = 'conflict' -- localPath - path to transformed markdown file -- modifiedTime - fetched from google server +* desiredLocalPath - slugified name. It is not unique, wikigdrive handles redirects so it is NOT real path in local system +* dirty - file needs to be downloaded +* conflicting - array of fileIds when mimeType = 'conflict' +* localPath - path to transformed markdown file +* modifiedTime - fetched from google server ``` { @@ -152,13 +152,13 @@ navWeight: -15 ### Transform stage: -0. Get files to transform (does not exist in local_files.json, have different modifiedTime, are trashed), generate desireLocalPaths based on parents -1. If file is removed - remove .md file, remove images -2. If file is new (not exists in local_files.json) - add to localFiles, schedule for generation -3. If file exists but with different desireLocalPath: - 3.1. Remove old .md, remove old images - 3.2. Schedule for generation - 3.3. Generate redir with old localPath -4. Remove dangling redirects -5. Check if there are any conflicts (same desireLocalPath) -6. Check if any conflicts can be removed +1. Get files to transform (does not exist in local_files.json, have different modifiedTime, are trashed), generate desireLocalPaths based on parents +2. If file is removed - remove .md file, remove images +3. If file is new (not exists in local_files.json) - add to localFiles, schedule for generation +4. If file exists but with different desireLocalPath: + * Remove old .md, remove old images + * Schedule for generation + * Generate redir with old localPath +5. Remove dangling redirects +6. Check if there are any conflicts (same desireLocalPath) +7. Check if any conflicts can be removed