diff --git a/.eslintignore b/.eslintignore index ebaf5e15..3722df27 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,8 +2,9 @@ /dist /db /scripts -*.config.js +*.config.{js,ts} .*.{js,ts} +/test/ # packages /node_modules/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb51904e..947cbd54 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} name: ${{ github.event.head_commit.message }} - tag: v${{ env.PACKAGE_VERSION}} + tag: v${{ env.PACKAGE_VERSION }} commit: ${{ github.sha }} artifacts: ./release.zip allowUpdates: true diff --git a/.gitignore b/.gitignore index 536eb755..a755aed3 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ lerna-debug.log* .DS_Store # Tests -/coverage +coverage/ /.nyc_output # IDEs and editors diff --git a/angular.json b/angular.json index cef12ea0..79ec803a 100644 --- a/angular.json +++ b/angular.json @@ -8,7 +8,7 @@ "eh-tag-editor": { "architect": { "build": { - "builder": "@angular-devkit/build-angular:browser", + "builder": "@angular-builders/custom-webpack:browser", "configurations": { "production": { "budgets": [ @@ -36,6 +36,9 @@ } }, "options": { + "customWebpackConfig": { + "path": "./angular.webpack.config.js" + }, "allowedCommonJsDependencies": ["markdown-it", "linkify-it", "parse5", "axios", "validator"], "assets": ["src/browser/favicon.ico", "src/browser/favicon.svg", "src/browser/assets"], "buildOptimizer": false, @@ -59,7 +62,7 @@ } }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular-builders/custom-webpack:dev-server", "configurations": { "production": { "browserTarget": "eh-tag-editor:build:production" diff --git a/angular.webpack.config.js b/angular.webpack.config.js new file mode 100644 index 00000000..812ffd70 --- /dev/null +++ b/angular.webpack.config.js @@ -0,0 +1,16 @@ +// @ts-check +import ResolveTypeScriptPlugin from 'resolve-typescript-plugin'; + +/** + * + * @param {import('webpack').Configuration} config + * @param {import('@angular-builders/custom-webpack').CustomWebpackBrowserSchema} options + * @param {import('@angular-builders/custom-webpack').TargetOptions} targetOptions + * @returns {import('webpack').Configuration} + */ +export default function (config, options, targetOptions) { + config.resolve ??= {}; + config.resolve.plugins ??= []; + config.resolve.plugins.push(new ResolveTypeScriptPlugin()); + return config; +} diff --git a/nest-cli.json b/nest-cli.json index e606c5a9..9205545b 100644 --- a/nest-cli.json +++ b/nest-cli.json @@ -4,7 +4,6 @@ "entryFile": "server/main", "compilerOptions": { "deleteOutDir": true, - "plugins": [{ "name": "@nestjs/swagger/plugin" }], "tsConfigPath": "src/server/tsconfig.json" } } diff --git a/package.json b/package.json index e6d6ff3c..ab1fe7cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "eh-tag-editor", - "version": "1.0.0", + "version": "2.0.0", + "type": "module", "engines": { "node": "16", "yarn": "1.22" @@ -8,7 +9,7 @@ "scripts": { "start:server": "nest start --debug --watch", "build:server": "nest build", - "test:server": "jest --config ./src/server/jest.config.js --coverage", + "test:server": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --config ./test/server/jest.config.js", "heroku-postbuild": "yarn build:server && yarn test:server && node scripts/server.js", "start:tool": "yarn build:tool --watch", "build:tool": "tsc --project ./src/tool", @@ -25,6 +26,9 @@ "browser": { "./src/shared/ehentai/http/config.ts": "./src/shared/ehentai/http/config.browser.ts" }, + "imports": { + "#*": "./dist/*.js" + }, "private": true, "dependencies": { "@actions/core": "~1.9.0", @@ -38,12 +42,11 @@ "@octokit/auth-oauth-app": "~4.3.1", "@octokit/rest": "~18.12.0", "axios": "~0.27.2", - "bluebird": "~3.7.2", "class-transformer": "~0.5.1", "class-validator": "~0.13.2", "cli-color": "~2.0.2", "commander": "~9.3.0", - "escape-string-regexp": "~4.0.0", + "escape-string-regexp": "~5.0.0", "fastify-swagger": "~5.2.0", "fs-extra": "~10.1.0", "idb-keyval": "~6.1.0", @@ -53,15 +56,16 @@ "markdown-it": "~13.0.1", "node-cache": "~5.1.2", "pako": "~2.0.4", - "parse5": "~6.0.0", + "parse5": "~7.0.0", "proxy-agent": "^5.0.0", "reflect-metadata": "~0.1.13", "rxjs": "~7.5.5", - "simple-git": "~3.7.1", + "simple-git": "~3.8.0", "source-map-support": "~0.5.21", "tslib": "~2.4.0" }, "devDependencies": { + "@angular-builders/custom-webpack": "^14.0.0", "@angular-devkit/build-angular": "^14.0.2", "@angular/animations": "^14.0.2", "@angular/cdk": "^14.0.2", @@ -79,7 +83,6 @@ "@nestjs/cli": "~8.2.6", "@nestjs/schematics": "~8.0.11", "@nestjs/testing": "~8.4.7", - "@types/bluebird-global": "~3.5.13", "@types/cli-color": "~2.0.2", "@types/fs-extra": "~9.0.13", "@types/jest": "~28.1.2", @@ -92,12 +95,14 @@ "@types/supertest": "~2.0.12", "@typescript-eslint/eslint-plugin": "~5.28.0", "@typescript-eslint/parser": "~5.28.0", + "cross-env": "^7.0.3", "eslint": "~8.18.0", "eslint-config-prettier": "~8.5.0", "eslint-plugin-prettier": "~4.0.0", "jest": "~28.1.1", "jest-to-match-shape-of": "~1.3.2", "prettier": "~2.7.1", + "resolve-typescript-plugin": "^1.2.0", "rimraf": "~3.0.2", "supertest": "~6.2.3", "ts-jest": "~28.0.5", diff --git a/scripts/info.js b/scripts/info.js index 0084ca91..68fad9e8 100644 --- a/scripts/info.js +++ b/scripts/info.js @@ -1,7 +1,8 @@ -const fs = require('fs-extra'); -const { exportVariable } = require('@actions/core'); +// @ts-check +import fs from 'fs-extra'; +import { exportVariable } from '@actions/core'; /** @type {import('type-fest').PackageJson} */ -const packageJson = fs.readJSONSync('./package.json'); +const packageJson = await fs.readJSON('./package.json'); exportVariable('PACKAGE_VERSION', packageJson.version); exportVariable('PACKAGE_NAME', packageJson.name); diff --git a/scripts/server.js b/scripts/server.js index 191f231d..56b1a688 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -1,10 +1,11 @@ -const fs = require('fs-extra'); +// @ts-check +import fs from 'fs-extra'; const removedPackages = ['lazysizes', 'zone.js']; const removedPackageHeaders = ['@angular', 'angular', '@actions/']; /** @type {import('type-fest').PackageJson} */ -const packageJson = fs.readJSONSync('./package.json'); +const packageJson = await fs.readJSON('./package.json'); packageJson.scripts = { start: 'node dist/server/main.js', }; @@ -14,4 +15,4 @@ for (const key in packageJson.dependencies) { packageJson.dependencies[key] = undefined; } } -fs.writeJSONSync('./package.json', packageJson); +await fs.writeJSON('./package.json', packageJson); diff --git a/scripts/tool.js b/scripts/tool.js index f9c84137..04b6ba20 100644 --- a/scripts/tool.js +++ b/scripts/tool.js @@ -1,18 +1,29 @@ -const fs = require('fs-extra'); +// @ts-check +import fs from 'fs-extra'; const removedPackages = ['lazysizes', 'zone.js']; const removedPackageHeaders = ['@angular', 'angular', '@nestjs/', 'fastify']; /** @type {import('type-fest').PackageJson} */ -const packageJson = fs.readJSONSync('./package.json'); -packageJson.scripts = { - start: 'node ./index.js', -}; +const packageJson = await fs.readJSON('./package.json'); +packageJson.scripts = undefined; packageJson.devDependencies = undefined; for (const key in packageJson.dependencies) { if (removedPackageHeaders.some((leading) => key.startsWith(leading)) || removedPackages.includes(key)) { packageJson.dependencies[key] = undefined; } } -fs.writeJSONSync('./dist/package.json', packageJson); -fs.writeFileSync('./dist/index.js', 'require("./tool")'); +for (const key in packageJson.imports) { + const value = packageJson.imports[key]; + if (typeof value == 'string') { + packageJson.imports[key] = value.replace(/^.\/dist\//, './'); + } +} +for (const key in /** @type {object} */ (packageJson.exports)) { + const value = packageJson.exports[key]; + if (typeof value == 'string') { + packageJson.exports[key] = value.replace(/^.\/dist\//, './'); + } +} +await fs.writeJSON('./dist/package.json', packageJson); +await fs.writeFile('./dist/index.js', 'import "./tool/index.js";'); diff --git a/src/browser/app/app.component.ts b/src/browser/app/app.component.ts index cee30111..7b6b8219 100644 --- a/src/browser/app/app.component.ts +++ b/src/browser/app/app.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { EhTagConnectorService } from 'browser/services/eh-tag-connector.service'; +import { EhTagConnectorService } from '#browser/services/eh-tag-connector.service'; import { Location } from '@angular/common'; -import { DbRepoService } from 'browser/services/db-repo.service'; +import { DbRepoService } from '#browser/services/db-repo.service'; @Component({ selector: 'app-root', diff --git a/src/browser/app/app.module.ts b/src/browser/app/app.module.ts index e8832b74..c5036b9c 100644 --- a/src/browser/app/app.module.ts +++ b/src/browser/app/app.module.ts @@ -31,8 +31,8 @@ import { EditorComponent } from './editor/editor.component'; import { GithubCornerComponent } from './github-corner/github-corner.component'; import { MarkPipe } from './shared/pipe/mark.pipe'; import { LinkifyPipe } from './shared/pipe/linkify.pipe'; -import { TitleService } from 'browser/services/title.service'; -import { ehHttpInterceptorProvider } from 'browser/services/eh-http-interceptor'; +import { TitleService } from '#browser/services/title.service'; +import { ehHttpInterceptorProvider } from '#browser/services/eh-http-interceptor'; @NgModule({ declarations: [ diff --git a/src/browser/app/editor.can-activate.ts b/src/browser/app/editor.can-activate.ts index cce68562..740c9fdf 100644 --- a/src/browser/app/editor.can-activate.ts +++ b/src/browser/app/editor.can-activate.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, UrlTree, Router } from '@angular/router'; -import { parseNamespace } from 'shared/namespace'; +import { parseNamespace } from '#shared/namespace'; @Injectable() export class CanActivateEditor implements CanActivate { diff --git a/src/browser/app/editor/editor.component.ts b/src/browser/app/editor/editor.component.ts index ebdb8c53..57790f4a 100644 --- a/src/browser/app/editor/editor.component.ts +++ b/src/browser/app/editor/editor.component.ts @@ -1,24 +1,24 @@ import { Component, OnInit } from '@angular/core'; -import { EhTagConnectorService } from 'browser/services/eh-tag-connector.service'; -import { RouteService } from 'browser/services/route.service'; +import { EhTagConnectorService } from '#browser/services/eh-tag-connector.service'; +import { RouteService } from '#browser/services/route.service'; import { Observable, BehaviorSubject, combineLatest, merge, lastValueFrom } from 'rxjs'; -import { editableNs, ETKey } from 'browser/interfaces/ehtranslation'; +import { editableNs, ETKey } from '#browser/interfaces/ehtranslation'; import { MatSnackBar } from '@angular/material/snack-bar'; import { FormControl, Validators, FormGroup, AbstractControl, ValidationErrors } from '@angular/forms'; import { map, tap, mergeMap, filter, shareReplay, debounceTime, distinctUntilChanged } from 'rxjs/operators'; -import { TitleService } from 'browser/services/title.service'; -import { GithubOauthService } from 'browser/services/github-oauth.service'; +import { TitleService } from '#browser/services/title.service'; +import { GithubOauthService } from '#browser/services/github-oauth.service'; import { trigger, state, style, transition, animate } from '@angular/animations'; -import { snackBarConfig } from 'browser/environments/environment'; -import { Tag, NamespaceName, FrontMatters } from 'shared/interfaces/ehtag'; -import { GithubReleaseService } from 'browser/services/github-release.service'; -import { DebugService } from 'browser/services/debug.service'; -import { DbRepoService } from 'browser/services/db-repo.service'; -import { RawTag, isRawTag } from 'shared/raw-tag'; -import { isNamespaceName } from 'shared/namespace'; -import { Context } from 'shared/markdown'; -import { suggestTag, Tag as TagSuggest } from 'shared/ehentai'; -import { namespaceMapToSearch, parseTag, tagAbbrFull } from 'shared/tag'; +import { snackBarConfig } from '#browser/environments/environment'; +import { Tag, NamespaceName, FrontMatters } from '#shared/interfaces/ehtag'; +import { GithubReleaseService } from '#browser/services/github-release.service'; +import { DebugService } from '#browser/services/debug.service'; +import { DbRepoService } from '#browser/services/db-repo.service'; +import { RawTag, isRawTag } from '#shared/raw-tag'; +import { isNamespaceName } from '#shared/namespace'; +import { Context } from '#shared/markdown'; +import { suggestTag, Tag as TagSuggest } from '#shared/ehentai'; +import { namespaceMapToSearch, parseTag, tagAbbrFull } from '#shared/tag'; class TagSuggestOption { constructor( diff --git a/src/browser/app/list/list.component.ts b/src/browser/app/list/list.component.ts index 224b1fbc..c178d91f 100644 --- a/src/browser/app/list/list.component.ts +++ b/src/browser/app/list/list.component.ts @@ -3,14 +3,14 @@ import type { SortDirection } from '@angular/material/sort'; import type { Params } from '@angular/router'; import { Observable, Subject, combineLatest, BehaviorSubject, from } from 'rxjs'; import { map, tap, shareReplay, debounceTime, filter, mergeMap } from 'rxjs/operators'; -import type { NamespaceName, Tag, RepoData } from 'shared/interfaces/ehtag'; -import { isNamespaceName } from 'shared/namespace'; +import type { NamespaceName, Tag, RepoData } from '#shared/interfaces/ehtag'; +import { isNamespaceName } from '#shared/namespace'; import { regexFromSearch } from '../shared/pipe/mark.pipe'; import { editableNs, ETKey } from '../../interfaces/ehtranslation'; -import { RouteService } from 'browser/services/route.service'; -import { DebugService } from 'browser/services/debug.service'; -import { TitleService } from 'browser/services/title.service'; -import { GithubReleaseService } from 'browser/services/github-release.service'; +import { RouteService } from '#browser/services/route.service'; +import { DebugService } from '#browser/services/debug.service'; +import { TitleService } from '#browser/services/title.service'; +import { GithubReleaseService } from '#browser/services/github-release.service'; export interface ETItem extends Tag<'raw'>, ETKey {} diff --git a/src/browser/app/user/user.component.ts b/src/browser/app/user/user.component.ts index 95eabd93..b37b7d3a 100644 --- a/src/browser/app/user/user.component.ts +++ b/src/browser/app/user/user.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { GithubOauthService } from 'browser/services/github-oauth.service'; -import type { GithubUser } from 'browser/interfaces/github'; -import { GithubReleaseService } from 'browser/services/github-release.service'; +import { GithubOauthService } from '#browser/services/github-oauth.service'; +import type { GithubUser } from '#browser/interfaces/github'; +import { GithubReleaseService } from '#browser/services/github-release.service'; import { finalize } from 'rxjs/operators'; @Component({ diff --git a/src/browser/interfaces/ehtranslation.ts b/src/browser/interfaces/ehtranslation.ts index 3fdc987d..397b4131 100644 --- a/src/browser/interfaces/ehtranslation.ts +++ b/src/browser/interfaces/ehtranslation.ts @@ -1,4 +1,4 @@ -import type { NamespaceName } from 'shared/interfaces/ehtag'; +import type { NamespaceName } from '#shared/interfaces/ehtag'; export interface ETKey { raw: string; diff --git a/src/browser/main.ts b/src/browser/main.ts index 18e8ca4b..4eeef28c 100644 --- a/src/browser/main.ts +++ b/src/browser/main.ts @@ -2,7 +2,6 @@ import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import Bluebird from 'bluebird'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; @@ -12,10 +11,6 @@ async function main(): Promise { enableProdMode(); } await platformBrowserDynamic().bootstrapModule(AppModule); - - const bluebirdPatchSymbol = Zone.__symbol__('bluebird') as keyof ZoneType; - const bluebirdPatch = Zone[bluebirdPatchSymbol] as (b: typeof Bluebird) => void; - bluebirdPatch(Bluebird); } main().catch((err) => console.error(err)); diff --git a/src/browser/polyfills.ts b/src/browser/polyfills.ts index 55c07f35..f1a62bbd 100644 --- a/src/browser/polyfills.ts +++ b/src/browser/polyfills.ts @@ -47,7 +47,6 @@ */ import 'zone.js'; // Included with Angular CLI. -import 'zone.js/plugins/zone-bluebird'; /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/src/browser/services/cache.service.ts b/src/browser/services/cache.service.ts index 96da426e..4a795039 100644 --- a/src/browser/services/cache.service.ts +++ b/src/browser/services/cache.service.ts @@ -1,4 +1,4 @@ -import type { RepoData } from 'shared/interfaces/ehtag'; +import type { RepoData } from '#shared/interfaces/ehtag'; import { Injectable } from '@angular/core'; import * as idb from 'idb-keyval'; diff --git a/src/browser/services/database.shared.ts b/src/browser/services/database.shared.ts index bb5da3d8..a94d87eb 100644 --- a/src/browser/services/database.shared.ts +++ b/src/browser/services/database.shared.ts @@ -7,11 +7,11 @@ import { FrontMatters, RepoData, RepoInfo, -} from 'shared/interfaces/ehtag'; -import type { DatabaseView, NamespaceDatabaseView } from 'shared/interfaces/database'; -import { Context } from 'shared/markdown'; -import type { RawTag } from 'shared/raw-tag'; -import { TagRecord } from 'shared/tag-record'; +} from '#shared/interfaces/ehtag'; +import type { DatabaseView, NamespaceDatabaseView } from '#shared/interfaces/database'; +import { Context } from '#shared/markdown'; +import type { RawTag } from '#shared/raw-tag'; +import { TagRecord } from '#shared/tag-record'; const fallback: Record> = { rows: { name: '行名', description: '标签列表的行名,即标签的命名空间。' }, diff --git a/src/browser/services/database.ts b/src/browser/services/database.ts index c0db70c2..7a5cb47a 100644 --- a/src/browser/services/database.ts +++ b/src/browser/services/database.ts @@ -1,4 +1,4 @@ -import type { TagType, RepoData } from 'shared/interfaces/ehtag'; +import type { TagType, RepoData } from '#shared/interfaces/ehtag'; import type { CacheService } from './cache.service'; import { DatabaseInMemory as DatabaseInMemoryBase } from './database.shared'; diff --git a/src/browser/services/database.worker.ts b/src/browser/services/database.worker.ts index 6c10a4c8..3b94c42c 100644 --- a/src/browser/services/database.worker.ts +++ b/src/browser/services/database.worker.ts @@ -1,6 +1,6 @@ /// -import type { TagType, RepoData } from './../../shared/interfaces/ehtag'; +import type { TagType, RepoData } from '#shared/interfaces/ehtag'; import { DatabaseInMemory } from './database.shared'; addEventListener('message', ({ data }) => { diff --git a/src/browser/services/db-repo.service.ts b/src/browser/services/db-repo.service.ts index edb01407..1ea27844 100644 --- a/src/browser/services/db-repo.service.ts +++ b/src/browser/services/db-repo.service.ts @@ -1,4 +1,4 @@ -import type { NamespaceName } from 'shared/interfaces/ehtag'; +import type { NamespaceName } from '#shared/interfaces/ehtag'; import { Injectable } from '@angular/core'; @Injectable({ diff --git a/src/browser/services/eh-tag-connector.service.ts b/src/browser/services/eh-tag-connector.service.ts index 07c7297c..2bdc9b82 100644 --- a/src/browser/services/eh-tag-connector.service.ts +++ b/src/browser/services/eh-tag-connector.service.ts @@ -4,11 +4,11 @@ import { Observable, of, throwError, OperatorFunction } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; import type { ETKey } from '../interfaces/ehtranslation'; import { ApiEndpointService } from './api-endpoint.service'; -import type { TagType, Tag, NamespaceName } from 'shared/interfaces/ehtag'; +import type { TagType, Tag, NamespaceName } from '#shared/interfaces/ehtag'; import { GithubReleaseService } from './github-release.service'; import { LocalStorageService } from './local-storage.service'; -import { TagRecord } from 'shared/tag-record'; -import { Context } from 'shared/markdown'; +import { TagRecord } from '#shared/tag-record'; +import { Context } from '#shared/markdown'; const EH_TAG_HASH = 'eh-tag-hash'; diff --git a/src/browser/services/github-release.service.ts b/src/browser/services/github-release.service.ts index 0fcc8438..68d022f8 100644 --- a/src/browser/services/github-release.service.ts +++ b/src/browser/services/github-release.service.ts @@ -1,13 +1,13 @@ import { Injectable, EventEmitter } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ApiEndpointService } from './api-endpoint.service'; -import type { GithubRelease } from 'browser/interfaces/github'; +import type { GithubRelease } from '#browser/interfaces/github'; import { DebugService } from './debug.service'; -import type { RepoData } from 'shared/interfaces/ehtag'; +import type { RepoData } from '#shared/interfaces/ehtag'; import { of, BehaviorSubject, merge, timer, from, Observable, lastValueFrom } from 'rxjs'; import { map, tap, mergeMap, catchError, filter, finalize, throttleTime } from 'rxjs/operators'; import { CacheService } from './cache.service'; -import type { DatabaseView } from 'shared/interfaces/database'; +import type { DatabaseView } from '#shared/interfaces/database'; import { DatabaseInMemory } from './database'; function notUndef(v: T | undefined): v is Exclude { @@ -66,7 +66,7 @@ export class GithubReleaseService { this.refreshEvent.next(-1); } private async set(value: RepoData<'raw'>): Promise { - await Promise.delay(0); + await new Promise((resolve) => setTimeout(resolve, 0)); const data = new DatabaseInMemory(this.cache, value, this.get().revision + 1); this.debug.log('release: rendering'); await data.render('full'); diff --git a/src/server/app/app.module.ts b/src/server/app/app.module.ts index c87c498f..7e001852 100644 --- a/src/server/app/app.module.ts +++ b/src/server/app/app.module.ts @@ -1,13 +1,13 @@ import { Module, ValidationPipe } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { APP_GUARD, APP_PIPE, APP_INTERCEPTOR, APP_FILTER } from '@nestjs/core'; -import { DatabaseModule } from '../database/database.module'; -import { ToolsModule } from '../tools/tools.module'; -import { LoggerInterceptor } from './logger.interceptor'; -import { OctokitModule } from '../octokit/octokit.module'; -import { GithubIdentityGuard } from './github-identity.guard'; -import { DebugFilter } from './debug.filter'; -import { AuthModule } from '../auth/auth.module'; +import { DatabaseModule } from '../database/database.module.js'; +import { ToolsModule } from '../tools/tools.module.js'; +import { OctokitModule } from '../octokit/octokit.module.js'; +import { AuthModule } from '../auth/auth.module.js'; +import { GithubIdentityGuard } from './github-identity.guard.js'; +import { DebugFilter } from './debug.filter.js'; +import { LoggerInterceptor } from './logger.interceptor.js'; @Module({ imports: [ConfigModule.forRoot({ isGlobal: true }), DatabaseModule, ToolsModule, OctokitModule, AuthModule], diff --git a/src/server/app/etag.interceptor.ts b/src/server/app/etag.interceptor.ts index c24761bb..7ffd700d 100644 --- a/src/server/app/etag.interceptor.ts +++ b/src/server/app/etag.interceptor.ts @@ -1,9 +1,9 @@ import { CallHandler, ExecutionContext, Injectable, NestInterceptor, HttpException, HttpStatus } from '@nestjs/common'; -import { DatabaseService } from '../database/database.service'; import type { FastifyRequest, FastifyReply } from 'fastify'; import { Observable, from, throwError, of } from 'rxjs'; import { map, mergeMap, delayWhen, catchError } from 'rxjs/operators'; -import { InjectableBase } from '../injectable-base'; +import { InjectableBase } from '../injectable-base.js'; +import { DatabaseService } from '../database/database.service.js'; function getSha(etag: unknown): string | undefined { if (typeof etag != 'string') return undefined; diff --git a/src/server/app/github-identity.guard.ts b/src/server/app/github-identity.guard.ts index d5ba8250..67dff5c5 100644 --- a/src/server/app/github-identity.guard.ts +++ b/src/server/app/github-identity.guard.ts @@ -1,7 +1,7 @@ import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'; import type { FastifyRequest } from 'fastify'; -import { InjectableBase } from '../injectable-base'; -import { OctokitService } from '../octokit/octokit.service'; +import { InjectableBase } from '../injectable-base.js'; +import { OctokitService } from '../octokit/octokit.service.js'; @Injectable() export class GithubIdentityGuard extends InjectableBase implements CanActivate { diff --git a/src/server/app/logger.interceptor.ts b/src/server/app/logger.interceptor.ts index ede6d4a2..80653665 100644 --- a/src/server/app/logger.interceptor.ts +++ b/src/server/app/logger.interceptor.ts @@ -1,8 +1,8 @@ import { CallHandler, ExecutionContext, Injectable, NestInterceptor, HttpException } from '@nestjs/common'; import type { FastifyRequest } from 'fastify'; import type { Observable } from 'rxjs'; -import { InjectableBase } from '../injectable-base'; import { tap } from 'rxjs/operators'; +import { InjectableBase } from '../injectable-base.js'; @Injectable() export class LoggerInterceptor extends InjectableBase implements NestInterceptor { diff --git a/src/server/auth/auth.controller.ts b/src/server/auth/auth.controller.ts index 58652401..ffe85752 100644 --- a/src/server/auth/auth.controller.ts +++ b/src/server/auth/auth.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Param, Query, Header, Headers, BadRequestException } from '@nestjs/common'; -import { InjectableBase } from '../injectable-base'; -import { AuthService, Authentication } from './auth.service'; import { ApiExcludeEndpoint } from '@nestjs/swagger'; +import { InjectableBase } from '../injectable-base.js'; +import { AuthService, Authentication } from './auth.service.js'; @Controller('auth') export class AuthController extends InjectableBase { diff --git a/src/server/auth/auth.module.ts b/src/server/auth/auth.module.ts index 7f52bc82..3770041c 100644 --- a/src/server/auth/auth.module.ts +++ b/src/server/auth/auth.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { AuthService } from './auth.service'; -import { AuthController } from './auth.controller'; -import { OctokitModule } from '../octokit/octokit.module'; +import { OctokitModule } from '../octokit/octokit.module.js'; +import { AuthService } from './auth.service.js'; +import { AuthController } from './auth.controller.js'; @Module({ imports: [OctokitModule], diff --git a/src/server/auth/auth.service.ts b/src/server/auth/auth.service.ts index 6055e5c1..ba877049 100644 --- a/src/server/auth/auth.service.ts +++ b/src/server/auth/auth.service.ts @@ -1,8 +1,9 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { InjectableBase } from '../injectable-base'; -import { OctokitService } from '../octokit/octokit.service'; import type { OAuthAppUserAuthentication, WebFlowAuthOptions } from '@octokit/auth-oauth-app/dist-types/types'; +import { InjectableBase } from '../injectable-base.js'; +import { OctokitService } from '../octokit/octokit.service.js'; + export { OAuthAppUserAuthentication as Authentication }; @Injectable() diff --git a/src/server/database/database-badge.controller.ts b/src/server/database/database-badge.controller.ts index 23192eb1..59ce2c08 100644 --- a/src/server/database/database-badge.controller.ts +++ b/src/server/database/database-badge.controller.ts @@ -1,10 +1,10 @@ import { Controller, Get, Param } from '@nestjs/common'; -import { DatabaseService } from './database.service'; -import { InjectableBase } from 'server/injectable-base'; -import { NamespaceName } from 'shared/interfaces/ehtag'; -import { NsParams } from './params.dto'; -import { Badge } from './database-badge.dto'; import { ApiTags } from '@nestjs/swagger'; +import { InjectableBase } from '../injectable-base.js'; +import { NamespaceName } from '#shared/interfaces/ehtag'; +import { DatabaseService } from './database.service.js'; +import { NsParams } from './params.dto.js'; +import { Badge } from './database-badge.dto.js'; @Controller('database') @ApiTags('Badge') diff --git a/src/server/database/database.controller.ts b/src/server/database/database.controller.ts index 6cc80fab..dd12cee9 100644 --- a/src/server/database/database.controller.ts +++ b/src/server/database/database.controller.ts @@ -1,3 +1,4 @@ +import { createRequire } from 'node:module'; import { Controller, UseInterceptors, @@ -16,10 +17,6 @@ import { Headers, HttpException, } from '@nestjs/common'; -import { InjectableBase } from 'server/injectable-base'; -import { DatabaseService } from './database.service'; -import { EtagInterceptor } from 'server/app/etag.interceptor'; -import type { TagType } from 'shared/interfaces/ehtag'; import { ApiTags, ApiOperation, @@ -28,13 +25,17 @@ import { ApiConflictResponse, ApiExcludeEndpoint, } from '@nestjs/swagger'; -import { RepoInfoDto, TagDto, TagResponseDto, LooseTagDto, NamespaceInfoDto } from 'server/dtos/repo-info.dto'; -import { NsParams, TagParams, PostTagQuery, PushEvent } from './params.dto'; -import { Format } from 'server/decorators/format.decorator'; -import type { UserInfo } from 'server/octokit/octokit.service'; -import { User } from 'server/decorators/user.decorator'; -import { ApiIfMatchHeader, ApiIfNoneMatchHeader } from 'server/decorators/swagger.decoretor'; -import { Context } from 'shared/markdown'; +import type { TagType } from '#shared/interfaces/ehtag'; +import { Context } from '#shared/markdown/index'; +import { InjectableBase } from '../injectable-base.js'; +import { ApiIfMatchHeader, ApiIfNoneMatchHeader } from '../decorators/swagger.decoretor.js'; +import { EtagInterceptor } from '../app/etag.interceptor.js'; +import { RepoInfoDto, TagDto, TagResponseDto, LooseTagDto, NamespaceInfoDto } from '../dtos/repo-info.dto.js'; +import { Format } from '../decorators/format.decorator.js'; +import type { UserInfo } from '../octokit/octokit.service.js'; +import { User } from '../decorators/user.decorator.js'; +import { DatabaseService } from './database.service.js'; +import { NsParams, TagParams, PostTagQuery, PushEvent } from './params.dto.js'; @Controller('database') @ApiTags('Database') diff --git a/src/server/database/database.module.ts b/src/server/database/database.module.ts index 234f06ff..64e6c132 100644 --- a/src/server/database/database.module.ts +++ b/src/server/database/database.module.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; -import { DatabaseService } from './database.service'; -import { DatabaseController } from './database.controller'; -import { OctokitModule } from 'server/octokit/octokit.module'; -import { DatabaseBadgeController } from './database-badge.controller'; +import { OctokitModule } from '../octokit/octokit.module.js'; +import { DatabaseService } from './database.service.js'; +import { DatabaseController } from './database.controller.js'; +import { DatabaseBadgeController } from './database-badge.controller.js'; @Module({ imports: [OctokitModule], diff --git a/src/server/database/database.service.ts b/src/server/database/database.service.ts index e97758db..336bdd4f 100644 --- a/src/server/database/database.service.ts +++ b/src/server/database/database.service.ts @@ -1,16 +1,16 @@ import { Injectable, OnModuleInit } from '@nestjs/common'; -import { InjectableBase } from 'server/injectable-base'; import { ConfigService } from '@nestjs/config'; import type { Octokit } from '@octokit/rest'; import type { AsyncReturnType } from 'type-fest'; import fs from 'fs-extra'; import path from 'path'; -import { Database } from 'shared/database'; -import { OctokitService, UserInfo } from 'server/octokit/octokit.service'; -import { Sha1Value, NamespaceName, Commit } from 'shared/interfaces/ehtag'; -import type { TagRecord } from 'shared/tag-record'; -import type { RawTag } from 'shared/raw-tag'; -import { Context } from 'shared/markdown'; +import { Database } from '#shared/database'; +import { Sha1Value, NamespaceName, Commit } from '#shared/interfaces/ehtag'; +import type { TagRecord } from '#shared/tag-record'; +import type { RawTag } from '#shared/raw-tag'; +import { Context } from '#shared/markdown/index'; +import { InjectableBase } from '../injectable-base.js'; +import { OctokitService, UserInfo } from '../octokit/octokit.service.js'; type User = AsyncReturnType['data']; diff --git a/src/server/database/params.dto.ts b/src/server/database/params.dto.ts index 81271d94..0dbe04ec 100644 --- a/src/server/database/params.dto.ts +++ b/src/server/database/params.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; -import { NamespaceName, Sha1Value } from 'shared/interfaces/ehtag'; import { IsIn, IsOptional } from 'class-validator'; -import { IsRawTag, RawTag } from 'shared/raw-tag'; +import { NamespaceName, Sha1Value } from '#shared/interfaces/ehtag'; +import { IsRawTag, RawTag } from '#shared/raw-tag'; export class NsParams { @ApiProperty({ description: '命名空间名称', diff --git a/src/server/decorators/format.decorator.ts b/src/server/decorators/format.decorator.ts index 8e830349..75eca360 100644 --- a/src/server/decorators/format.decorator.ts +++ b/src/server/decorators/format.decorator.ts @@ -2,7 +2,7 @@ import { createParamDecorator, ExecutionContext, BadRequestException, Header } f import type { FastifyRequest } from 'fastify'; import { ApiQuery, ApiProduces } from '@nestjs/swagger'; import { __decorate } from 'tslib'; -import type { TagType } from 'shared/interfaces/ehtag'; +import type { TagType } from '#shared/interfaces/ehtag'; function getFromQuery(format: string): TagType { format = format.trim().toLowerCase(); diff --git a/src/server/decorators/user.decorator.ts b/src/server/decorators/user.decorator.ts index 9a6ad979..bd4de7f0 100644 --- a/src/server/decorators/user.decorator.ts +++ b/src/server/decorators/user.decorator.ts @@ -2,7 +2,7 @@ import { createParamDecorator, ExecutionContext, UnauthorizedException } from '@ import type { FastifyRequest } from 'fastify'; import { ApiBearerAuth } from '@nestjs/swagger'; import { __decorate } from 'tslib'; -import type { UserInfo } from '../octokit/octokit.service'; +import type { UserInfo } from '../octokit/octokit.service.js'; export const User = createParamDecorator( (_: void, ctx: ExecutionContext) => { diff --git a/src/server/dtos/repo-info.dto.ts b/src/server/dtos/repo-info.dto.ts index 454eb487..46181f24 100644 --- a/src/server/dtos/repo-info.dto.ts +++ b/src/server/dtos/repo-info.dto.ts @@ -1,3 +1,5 @@ +import { ApiProperty, OmitType } from '@nestjs/swagger'; +import { IsString, MinLength } from 'class-validator'; import { RepoInfo, Commit, @@ -9,9 +11,7 @@ import { RepoData, NamespaceData, Tag, -} from 'shared/interfaces/ehtag'; -import { ApiProperty, OmitType } from '@nestjs/swagger'; -import { IsString, MinLength } from 'class-validator'; +} from '#shared/interfaces/ehtag'; export class SignatureDto implements Signature { name!: string; diff --git a/src/server/jest.config.js b/src/server/jest.config.js deleted file mode 100644 index 5ba0e8b7..00000000 --- a/src/server/jest.config.js +++ /dev/null @@ -1,25 +0,0 @@ -const path = require('path'); - -/** @typedef {import('ts-jest')} */ -/** @type {import('@jest/types').Config.InitialOptions} */ -const config = { - moduleFileExtensions: ['js', 'json', 'ts'], - rootDir: path.resolve(__dirname, '../..'), - roots: ['/src/'], - setupFilesAfterEnv: ['/src/server/setup-jest.ts'], - moduleNameMapper: { - '^shared/.*$': '/src/$0', - '^server/.*$': '/src/$0', - }, - testEnvironment: 'node', - testRegex: '(\\.test|\\.spec)\\.ts$', - transform: { - '^.+\\.(t|j)s$': 'ts-jest', - }, - globals: { - 'ts-jest': { - tsconfig: path.resolve(__dirname, './tsconfig.test.json'), - }, - }, -}; -module.exports = config; diff --git a/src/server/main.ts b/src/server/main.ts index d19e47c9..d3255a81 100644 --- a/src/server/main.ts +++ b/src/server/main.ts @@ -1,10 +1,9 @@ -import '../shared/init'; import { NestFactory } from '@nestjs/core'; -import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; -import { AppModule } from './app/app.module'; -import { ConfigService } from '@nestjs/config'; import { Logger } from '@nestjs/common'; -import { setupSwagger, enableCors } from './setup'; +import { ConfigService } from '@nestjs/config'; +import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; +import { AppModule } from './app/app.module.js'; +import { setupSwagger, enableCors } from './setup.js'; const logger = new Logger('Main', { timestamp: true }); /** diff --git a/src/server/octokit/octokit.module.ts b/src/server/octokit/octokit.module.ts index 0f16d303..9ffe65d8 100644 --- a/src/server/octokit/octokit.module.ts +++ b/src/server/octokit/octokit.module.ts @@ -1,5 +1,5 @@ import { Module } from '@nestjs/common'; -import { OctokitService } from './octokit.service'; +import { OctokitService } from './octokit.service.js'; @Module({ providers: [OctokitService], diff --git a/src/server/octokit/octokit.service.ts b/src/server/octokit/octokit.service.ts index 8e7ba4d7..80f46601 100644 --- a/src/server/octokit/octokit.service.ts +++ b/src/server/octokit/octokit.service.ts @@ -1,13 +1,13 @@ +import type { AsyncReturnType } from 'type-fest'; +import Cache from 'node-cache'; import { Injectable, OnModuleInit } from '@nestjs/common'; -import { InjectableBase } from 'server/injectable-base'; +import { ConfigService } from '@nestjs/config'; import { Octokit } from '@octokit/rest'; import type { OctokitOptions } from '@octokit/core/dist-types/types'; -import { ConfigService } from '@nestjs/config'; import { createAppAuth, StrategyOptions } from '@octokit/auth-app'; import { createOAuthAppAuth } from '@octokit/auth-oauth-app'; -import type { AsyncReturnType } from 'type-fest'; -import Cache from 'node-cache'; -import type { Sha1Value, Commit, Signature } from 'shared/interfaces/ehtag'; +import { InjectableBase } from '../injectable-base.js'; +import type { Sha1Value, Commit, Signature } from '#shared/interfaces/ehtag'; export type AppInfo = NonNullable['data']>>; export type UserInfo = Readonly['data']>; @@ -104,20 +104,21 @@ export class OctokitService extends InjectableBase implements OnModuleInit { private appToken?: Promise>; async getAppToken(): Promise { - if ( - this.appToken?.isPending() || - (this.appToken?.isFulfilled() && Date.parse((await this.appToken).expires_at) > Date.now() + 600_000) - ) - return this.appToken.get('token'); + const currentQuery = await this.appToken; + if (currentQuery && Date.parse(currentQuery.expires_at) > Date.now() + 600_000) { + return currentQuery.token; + } + const tokenReq = this.forApp.apps.createInstallationAccessToken({ installation_id: this.APP_INSTALLATION_ID, }); - return (this.appToken = tokenReq.then((token) => { + this.appToken = tokenReq.then((token) => { this._forRepo = this.createOctokit({ auth: token.data.token, }); return token.data; - })).get('token'); + }); + return (await this.appToken).token; } async user(userToken: string): Promise { const cache = this.userInfoCache.get(userToken); diff --git a/src/server/tools/tools.controller.ts b/src/server/tools/tools.controller.ts index eb25099f..7d2351de 100644 --- a/src/server/tools/tools.controller.ts +++ b/src/server/tools/tools.controller.ts @@ -1,14 +1,14 @@ import { Controller, Post, Body, HttpCode, HttpStatus, Param, BadRequestException } from '@nestjs/common'; -import { TagResponseDto, LooseTagDto } from 'server/dtos/repo-info.dto'; -import { Format } from 'server/decorators/format.decorator'; -import type { TagType } from 'shared/interfaces/ehtag'; -import { TagRecord } from 'shared/tag-record'; -import { InjectableBase } from 'server/injectable-base'; -import { DatabaseService } from 'server/database/database.service'; -import { RawTag } from 'shared/raw-tag'; +import { TagResponseDto, LooseTagDto } from '../dtos/repo-info.dto.js'; +import { Format } from '../decorators/format.decorator.js'; +import type { TagType } from '#shared/interfaces/ehtag'; +import { TagRecord } from '#shared/tag-record'; +import { InjectableBase } from '../injectable-base.js'; +import { DatabaseService } from '../database/database.service.js'; +import { RawTag } from '#shared/raw-tag'; import { ApiOperation, ApiConsumes, ApiTags, ApiProduces, ApiOkResponse, ApiBody } from '@nestjs/swagger'; -import { TagParams, ParsedLine } from './tools.dto'; -import { Context } from 'shared/markdown'; +import { TagParams, ParsedLine } from './tools.dto.js'; +import { Context } from '#shared/markdown/index'; @ApiTags('Tools') @Controller('tools') diff --git a/src/server/tools/tools.dto.ts b/src/server/tools/tools.dto.ts index 5321a7b3..f1f5d04e 100644 --- a/src/server/tools/tools.dto.ts +++ b/src/server/tools/tools.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import type { TagResponseDto } from 'server/dtos/repo-info.dto'; import { IsString } from 'class-validator'; +import type { TagResponseDto } from '../dtos/repo-info.dto.js'; export class TagParams { @ApiProperty({ type: String, description: '原始标签' }) diff --git a/src/server/tools/tools.module.ts b/src/server/tools/tools.module.ts index 52d420aa..ba4b5a14 100644 --- a/src/server/tools/tools.module.ts +++ b/src/server/tools/tools.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; -import { ToolsService } from './tools.service'; -import { ToolsController } from './tools.controller'; -import { DatabaseModule } from 'server/database/database.module'; +import { ToolsService } from './tools.service.js'; +import { ToolsController } from './tools.controller.js'; +import { DatabaseModule } from '../database/database.module.js'; @Module({ imports: [DatabaseModule], diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json index 3b4e9c5c..eec16c09 100644 --- a/src/server/tsconfig.json +++ b/src/server/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../tsconfig.json", "compilerOptions": { "target": "ES2018", - "module": "CommonJS", + "module": "ESNext", + "moduleResolution": "Node", "outDir": "../../dist", "lib": ["ES2018"] }, diff --git a/src/server/tsconfig.test.json b/src/server/tsconfig.test.json deleted file mode 100644 index b9355add..00000000 --- a/src/server/tsconfig.test.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "types": ["node", "bluebird-global", "jest", "jest-to-match-shape-of"] - } -} diff --git a/src/shared/cell.ts b/src/shared/cell.ts index 18deba0f..d225f202 100644 --- a/src/shared/cell.ts +++ b/src/shared/cell.ts @@ -1,7 +1,6 @@ -import type { CellType, TagType } from './interfaces/ehtag'; -import { parse, render } from './markdown'; -import type { Context } from './markdown'; -import type { Tree } from './interfaces/ehtag.ast'; +import type { CellType, TagType } from './interfaces/ehtag.js'; +import { parse, render, type Context } from './markdown/index.js'; +import type { Tree } from './interfaces/ehtag.ast.js'; export class Cell { constructor(raw: string) { diff --git a/src/shared/database.ts b/src/shared/database.ts index 31d3afc9..75877967 100644 --- a/src/shared/database.ts +++ b/src/shared/database.ts @@ -1,12 +1,12 @@ import fs from 'fs-extra'; import path from 'path'; -import { NamespaceDatabase } from './namespace-database'; -import { NamespaceName, RepoInfo, Sha1Value, RepoData, TagType } from './interfaces/ehtag'; -import type { TagRecord } from './tag-record'; -import type { RawTag } from './raw-tag'; -import type { DatabaseView } from './interfaces/database'; -import { Logger } from './markdown'; -import { GitRepoInfoProvider, RepoInfoProvider } from './repo-info-provider'; +import { NamespaceDatabase } from './namespace-database.js'; +import { NamespaceName, RepoInfo, Sha1Value, RepoData, TagType } from './interfaces/ehtag.js'; +import type { TagRecord } from './tag-record.js'; +import type { RawTag } from './raw-tag.js'; +import type { DatabaseView } from './interfaces/database.js'; +import { Logger } from './markdown/index.js'; +import { GitRepoInfoProvider, RepoInfoProvider } from './repo-info-provider.js'; const SUPPORTED_REPO_VERSION = 6; export class Database implements DatabaseView { diff --git a/src/shared/ehentai/get-tag-groups.ts b/src/shared/ehentai/get-tag-groups.ts index c497a4a3..539d708c 100644 --- a/src/shared/ehentai/get-tag-groups.ts +++ b/src/shared/ehentai/get-tag-groups.ts @@ -1,7 +1,7 @@ -import { isRawTag } from '../raw-tag'; -import { isNamespaceName } from '../namespace'; -import { get } from './http'; -import { MasterTag, store } from './tag'; +import { isRawTag } from '../raw-tag.js'; +import { isNamespaceName } from '../namespace.js'; +import { get } from './http/index.js'; +import { MasterTag, store } from './tag.js'; /** * 通过 https://repo.e-hentai.org/tools.php?act=taggroup diff --git a/src/shared/ehentai/http/api.ts b/src/shared/ehentai/http/api.ts index 37e620db..ba601aea 100644 --- a/src/shared/ehentai/http/api.ts +++ b/src/shared/ehentai/http/api.ts @@ -1,4 +1,4 @@ -import { request } from './core'; +import { request } from './core.js'; const responseType = Symbol(); diff --git a/src/shared/ehentai/http/core.ts b/src/shared/ehentai/http/core.ts index fbdf1b22..5356bc70 100644 --- a/src/shared/ehentai/http/core.ts +++ b/src/shared/ehentai/http/core.ts @@ -1,5 +1,5 @@ import axios, { AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios'; -import { config as defaultConfig } from './config'; +import { config as defaultConfig } from './config.js'; const delay = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/src/shared/ehentai/http/html.ts b/src/shared/ehentai/http/html.ts index 6ce90956..75c945e3 100644 --- a/src/shared/ehentai/http/html.ts +++ b/src/shared/ehentai/http/html.ts @@ -1,8 +1,8 @@ import type { AxiosResponse } from 'axios'; -import { request } from './core'; -import { parse, Document } from 'parse5'; +import { request } from './core.js'; +import { parse, DefaultTreeAdapterMap } from 'parse5'; -export type { Document }; +export type Document = DefaultTreeAdapterMap['document']; export async function html(url: string): Promise> { const response = await request( { diff --git a/src/shared/ehentai/http/index.ts b/src/shared/ehentai/http/index.ts index f6e8e735..8c44d458 100644 --- a/src/shared/ehentai/http/index.ts +++ b/src/shared/ehentai/http/index.ts @@ -1,8 +1,8 @@ import type { AxiosResponse } from 'axios'; -import { request } from './core'; +import { request } from './core.js'; -export * from './api'; -export * from './html'; +export * from './api.js'; +export * from './html.js'; export { request }; diff --git a/src/shared/ehentai/index.ts b/src/shared/ehentai/index.ts index a895a0bd..6eb921ae 100644 --- a/src/shared/ehentai/index.ts +++ b/src/shared/ehentai/index.ts @@ -1,4 +1,4 @@ -export { normalizeTag } from './normalize-tag'; -export { suggestTag } from './suggest-tag'; -export { getTagGroups } from './get-tag-groups'; -export type { Tag } from './tag'; +export { normalizeTag } from './normalize-tag.js'; +export { suggestTag } from './suggest-tag.js'; +export { getTagGroups } from './get-tag-groups.js'; +export type { Tag } from './tag.js'; diff --git a/src/shared/ehentai/normalize-tag.ts b/src/shared/ehentai/normalize-tag.ts index c87eec1f..6b65b9a3 100644 --- a/src/shared/ehentai/normalize-tag.ts +++ b/src/shared/ehentai/normalize-tag.ts @@ -1,9 +1,9 @@ -import { isRawTag, RawTag } from '../raw-tag'; -import type { NamespaceName } from '../interfaces/ehtag'; -import { isNamespaceName } from '../namespace'; -import { suggestTag } from './suggest-tag'; -import { get } from './http'; -import { Tag, tagCache } from './tag'; +import { isRawTag, RawTag } from '../raw-tag.js'; +import type { NamespaceName } from '../interfaces/ehtag.js'; +import { isNamespaceName } from '../namespace.js'; +import { suggestTag } from './suggest-tag.js'; +import { get } from './http/index.js'; +import { Tag, tagCache } from './tag.js'; const tagsFoundBySearch = new Set<`${NamespaceName}:${RawTag}`>(); diff --git a/src/shared/ehentai/suggest-tag.ts b/src/shared/ehentai/suggest-tag.ts index 3e30d27c..df1afe93 100644 --- a/src/shared/ehentai/suggest-tag.ts +++ b/src/shared/ehentai/suggest-tag.ts @@ -1,7 +1,7 @@ -import type { RawTag } from '../raw-tag'; -import { api, ApiRequest, ResponseOf } from './http'; -import type { NamespaceName } from '../interfaces/ehtag'; -import { SlaveTag, store, Tag } from './tag'; +import type { RawTag } from '../raw-tag.js'; +import { api, ApiRequest, ResponseOf } from './http/index.js'; +import type { NamespaceName } from '../interfaces/ehtag.js'; +import { SlaveTag, store, Tag } from './tag.js'; interface TagSuggestRequest extends ApiRequest< diff --git a/src/shared/ehentai/tag.ts b/src/shared/ehentai/tag.ts index 6efc7b67..bd7d2456 100644 --- a/src/shared/ehentai/tag.ts +++ b/src/shared/ehentai/tag.ts @@ -1,5 +1,5 @@ -import type { NamespaceName } from '../interfaces/ehtag'; -import type { RawTag } from '../raw-tag'; +import type { NamespaceName } from '../interfaces/ehtag.js'; +import type { RawTag } from '../raw-tag.js'; export interface MasterTag { id: number; diff --git a/src/shared/init.ts b/src/shared/init.ts deleted file mode 100644 index 313e5b1b..00000000 --- a/src/shared/init.ts +++ /dev/null @@ -1,10 +0,0 @@ -import 'source-map-support/register'; -import { Promise } from 'bluebird'; - -if (globalThis.Promise !== (Promise as unknown)) - Object.defineProperty(globalThis, 'Promise', { - value: Promise, - writable: false, - enumerable: true, - configurable: true, - }); diff --git a/src/shared/interfaces/database.ts b/src/shared/interfaces/database.ts index 1cb37e5a..e08c9f41 100644 --- a/src/shared/interfaces/database.ts +++ b/src/shared/interfaces/database.ts @@ -1,6 +1,14 @@ -import type { RepoInfo, TagType, RepoData, NamespaceName, FrontMatters, NamespaceInfo, NamespaceData } from './ehtag'; -import type { RawTag } from '../raw-tag'; -import type { TagRecord } from '../tag-record'; +import type { + RepoInfo, + TagType, + RepoData, + NamespaceName, + FrontMatters, + NamespaceInfo, + NamespaceData, +} from './ehtag.js'; +import type { RawTag } from '../raw-tag.js'; +import type { TagRecord } from '../tag-record.js'; export interface NamespaceDatabaseView { readonly name: NamespaceName; diff --git a/src/shared/interfaces/ehtag.ast.ts b/src/shared/interfaces/ehtag.ast.ts index 4f42c58e..b9f0caf8 100644 --- a/src/shared/interfaces/ehtag.ast.ts +++ b/src/shared/interfaces/ehtag.ast.ts @@ -1,5 +1,5 @@ -import type { RawTag } from '../raw-tag'; -import type { NamespaceName } from './ehtag'; +import type { RawTag } from '../raw-tag.js'; +import type { NamespaceName } from './ehtag.js'; export type Tree = ParaNode[]; diff --git a/src/shared/interfaces/ehtag.ts b/src/shared/interfaces/ehtag.ts index 8485c59c..b66ceb76 100644 --- a/src/shared/interfaces/ehtag.ts +++ b/src/shared/interfaces/ehtag.ts @@ -1,4 +1,4 @@ -import type * as Ast from './ehtag.ast'; +import type * as Ast from './ehtag.ast.js'; import type { Opaque } from 'type-fest'; /** 表示一个 SHA1 字符串,用来记录 Git 版本 */ diff --git a/src/shared/markdown/context.ts b/src/shared/markdown/context.ts index 7f7ec819..dd236c2f 100644 --- a/src/shared/markdown/context.ts +++ b/src/shared/markdown/context.ts @@ -1,7 +1,7 @@ -import type { TagRecord } from '../tag-record'; -import type { RawTag } from '../raw-tag'; -import type { NamespaceDatabaseView, DatabaseView } from '../interfaces/database'; -import type { Database } from '../database'; +import type { TagRecord } from '../tag-record.js'; +import type { RawTag } from '../raw-tag.js'; +import type { NamespaceDatabaseView, DatabaseView } from '../interfaces/database.js'; +import type { Database } from '../database.js'; export abstract class Logger { info(context: Context, message: string): void { diff --git a/src/shared/markdown/html-renderer.ts b/src/shared/markdown/html-renderer.ts index eed1e5ef..4b4db9cd 100644 --- a/src/shared/markdown/html-renderer.ts +++ b/src/shared/markdown/html-renderer.ts @@ -1,4 +1,4 @@ -import { Attribute, EndLocation, serialize, SerializerOptions, TypedTreeAdapter } from 'parse5'; +import { serialize, SerializerOptions, TreeAdapterTypeMap, TreeAdapter, html, Token } from 'parse5'; import { BreakNode, ContainerNode, @@ -16,9 +16,9 @@ import { NodeMap, isContainer, isNodeType, -} from '../interfaces/ehtag.ast'; -import { renderText } from './text-renderer'; -import { tagAbbr } from '../tag'; +} from '../interfaces/ehtag.ast.js'; +import { renderText } from './text-renderer.js'; +import { tagAbbr } from '../tag.js'; const FRAGMENT_NODE = '#root'; export interface DocumentFragment { @@ -28,7 +28,7 @@ export interface DocumentFragment { const props = { parent: new WeakMap(), - namespaceURI: new WeakMap(), + namespaceURI: new WeakMap(), }; type Props = keyof typeof props; type PropValue = typeof props[T] extends WeakMap ? V : never; @@ -47,7 +47,7 @@ function setProp(node: Node, key: T, value?: PropV } } -function getAttr(attrs: Attribute[], name: string): string | undefined { +function getAttr(attrs: Token.Attribute[], name: string): string | undefined { const attr = attrs.find((a) => a.name === name); return attr?.value; } @@ -69,7 +69,7 @@ interface __Template { } interface __UnknownNode { type: string; - attrs: Attribute[]; + attrs: Token.Attribute[]; } // interface NodeMapEx extends NodeMap { @@ -80,20 +80,20 @@ interface __UnknownNode { // [TEMPLATE_NODE]: __Template; // } -interface TreeAdapterTypeMap { - attribute: Attribute; - childNode: Node; - commentNode: __CommentNode; - document: __Document; - documentFragment: DocumentFragment; - documentType: import('parse5').DocumentType; - element: Node; - node: Node; - parentNode: Node; - textNode: TextNode; -} +type MyTreeAdapterTypeMap = TreeAdapterTypeMap< + Node, + __Document | DocumentFragment | Node, + Node, + __Document, + DocumentFragment, + Node, + __CommentNode, + TextNode, + never, + never +>; -const ELEMENT_MAP: Record Node> = { +const ELEMENT_MAP: Record Node> = { a(attrs): LinkNode { return { type: 'link', @@ -152,7 +152,7 @@ const ELEMENT_MAP: Record Node> = { }, }; const ATTR_MAP: { - [T in NodeType]: undefined | ((node: NodeMap[T]) => Attribute[]); + [T in NodeType]: undefined | ((node: NodeMap[T]) => Token.Attribute[]); } = { link(node) { const attr = [{ name: 'href', value: node.url }]; @@ -204,16 +204,16 @@ const TAG_NAME_MAP: { text: undefined, }; -class SerializeTreeAdapter implements TypedTreeAdapter { +class SerializeTreeAdapter implements TreeAdapter { constructor( private readonly _ELEMENT_MAP: typeof ELEMENT_MAP, private readonly _ATTR_MAP: typeof ATTR_MAP, private readonly _TAG_NAME_MAP: typeof TAG_NAME_MAP, ) {} - updateNodeSourceCodeLocation(_node: Node, _location: EndLocation): void { + updateNodeSourceCodeLocation(_node: Node, _location: Partial): void { throw new Error('Method not implemented.'); } - adoptAttributes(_recipient: Node, _attrs: Attribute[]): void { + adoptAttributes(_recipient: Node, _attrs: Token.Attribute[]): void { throw new Error('Method not implemented.'); } appendChild(parentNode: ContainerNode, newNode: InlineNode): void { @@ -230,7 +230,7 @@ class SerializeTreeAdapter implements TypedTreeAdapter { createDocumentFragment(): DocumentFragment { return { type: FRAGMENT_NODE, content: [] }; } - createElement(tagName: string, namespaceURI: string, attrs: Attribute[]): Node { + createElement(tagName: string, namespaceURI: html.NS, attrs: Token.Attribute[]): Node { const creater = this._ELEMENT_MAP[tagName]; const node: Node = creater ? creater(attrs) @@ -249,7 +249,7 @@ class SerializeTreeAdapter implements TypedTreeAdapter { setProp(node, 'parent'); } } - getAttrList(element: Node): Attribute[] { + getAttrList(element: Node): Token.Attribute[] { if ('attrs' in element) return (element as __UnknownNode).attrs ?? []; const attrList = this._ATTR_MAP[element.type]; if (attrList) return attrList(element as never); @@ -263,27 +263,25 @@ class SerializeTreeAdapter implements TypedTreeAdapter { getCommentNodeContent(commentNode: __CommentNode): string { return commentNode.text; } - getDocumentMode(_document: __Document): import('parse5').DocumentMode { + getDocumentMode(_document: __Document): html.DOCUMENT_MODE { throw new Error('Method not implemented.'); } - getDocumentTypeNodeName(_doctypeNode: import('parse5').DocumentType): string { + getDocumentTypeNodeName(_doctypeNode: never): string { throw new Error('Method not implemented.'); } - getDocumentTypeNodePublicId(_doctypeNode: import('parse5').DocumentType): string { + getDocumentTypeNodePublicId(_doctypeNode: never): string { throw new Error('Method not implemented.'); } - getDocumentTypeNodeSystemId(_doctypeNode: import('parse5').DocumentType): string { + getDocumentTypeNodeSystemId(_doctypeNode: never): string { throw new Error('Method not implemented.'); } getFirstChild(node: ContainerNode): Node { return this.getChildNodes(node)[0]; } - getNamespaceURI(element: Node): string { - return getProp(element, 'namespaceURI') ?? ''; + getNamespaceURI(element: Node): html.NS { + return getProp(element, 'namespaceURI') ?? html.NS.HTML; } - getNodeSourceCodeLocation( - _node: Node, - ): import('parse5').Location | import('parse5').StartTagLocation | import('parse5').ElementLocation { + getNodeSourceCodeLocation(_node: Node): Token.ElementLocation | undefined | null { throw new Error('Method not implemented.'); } getParentNode(node: Node): ContainerNode { @@ -316,7 +314,7 @@ class SerializeTreeAdapter implements TypedTreeAdapter { isCommentNode(node: Node | __CommentNode): node is __CommentNode { return node.type === COMMENT_NODE; } - isDocumentTypeNode(_node: Node | import('parse5').DocumentType): _node is import('parse5').DocumentType { + isDocumentTypeNode(_node: Node): _node is never { return false; } isElementNode(node: Node): node is Node { @@ -329,23 +327,20 @@ class SerializeTreeAdapter implements TypedTreeAdapter { isTextNode(node: Node): node is TextNode { return node.type === 'text'; } - setDocumentMode(_document: __Document, _mode: import('parse5').DocumentMode): void { + setDocumentMode(_document: __Document, _mode: html.DOCUMENT_MODE): void { throw new Error('Method not implemented.'); } setDocumentType(_document: __Document, _name: string, _publicId: string, _systemId: string): void { throw new Error('Method not implemented.'); } - setNodeSourceCodeLocation( - _node: Node, - _location: import('parse5').Location | import('parse5').StartTagLocation | import('parse5').ElementLocation, - ): void { + setNodeSourceCodeLocation(_node: Node, _location: Token.ElementLocation | null): void { throw new Error('Method not implemented.'); } setTemplateContent(templateElement: __Template | Node, contentElement: DocumentFragment): void { (templateElement as __Template).template = contentElement; } } -const options: SerializerOptions = { +const options: SerializerOptions = { treeAdapter: new SerializeTreeAdapter(ELEMENT_MAP, ATTR_MAP, TAG_NAME_MAP), }; export function renderHtml(node: Node | Tree): string { diff --git a/src/shared/markdown/index.ts b/src/shared/markdown/index.ts index 6f34c074..ab97b60e 100644 --- a/src/shared/markdown/index.ts +++ b/src/shared/markdown/index.ts @@ -1,11 +1,11 @@ -import type { CellType, TagType } from '../interfaces/ehtag'; -import { renderText } from './text-renderer'; -import { renderHtml } from './html-renderer'; -import { renderMd } from './md-renderer'; -import { parseMd } from './md-parser'; -import type { Context } from './context'; -export * from './context'; -import type { Tree } from '../interfaces/ehtag.ast'; +import type { CellType, TagType } from '../interfaces/ehtag.js'; +import { renderText } from './text-renderer.js'; +import { renderHtml } from './html-renderer.js'; +import { renderMd } from './md-renderer.js'; +import { parseMd } from './md-parser.js'; +import type { Context } from './context.js'; +export * from './context.js'; +import type { Tree } from '../interfaces/ehtag.ast.js'; export function parse(src: string, context: Context): Tree { const ast = parseMd(src, context); return ast; diff --git a/src/shared/markdown/md-parser.ts b/src/shared/markdown/md-parser.ts index 44820ee3..b49d63fe 100644 --- a/src/shared/markdown/md-parser.ts +++ b/src/shared/markdown/md-parser.ts @@ -1,4 +1,8 @@ import MarkdownIt from 'markdown-it'; +import type Token from 'markdown-it/lib/token.js'; +import type { FixedLengthArray } from 'type-fest'; +import { Context } from './context.js'; +import type { NamespaceName } from '../interfaces/ehtag.js'; import { Tree, ParaNode, @@ -11,12 +15,8 @@ import { isNodeType, EmphasisNode, StrongNode, -} from '../interfaces/ehtag.ast'; -import type Token from 'markdown-it/lib/token'; -import { Context } from './context'; -import type { NamespaceName } from '../interfaces/ehtag'; -import { parseTag } from '../tag'; -import type { FixedLengthArray } from 'type-fest'; +} from '../interfaces/ehtag.ast.js'; +import { parseTag } from '../tag.js'; const md = MarkdownIt('commonmark', { html: false, diff --git a/src/shared/markdown/md-renderer.ts b/src/shared/markdown/md-renderer.ts index fbeddd3b..e34b4981 100644 --- a/src/shared/markdown/md-renderer.ts +++ b/src/shared/markdown/md-renderer.ts @@ -1,5 +1,5 @@ -import { tagAbbrFull } from '../tag'; -import type { Node, Tree, NodeType, NodeMap, ContainerNode } from '../interfaces/ehtag.ast'; +import { tagAbbrFull } from '../tag.js'; +import type { Node, Tree, NodeType, NodeMap, ContainerNode } from '../interfaces/ehtag.ast.js'; function encodeUrl(url: string): string { return url; diff --git a/src/shared/markdown/text-renderer.ts b/src/shared/markdown/text-renderer.ts index 5a952c8b..fc5f9a9a 100644 --- a/src/shared/markdown/text-renderer.ts +++ b/src/shared/markdown/text-renderer.ts @@ -1,5 +1,5 @@ -import { tagAbbr } from '../tag'; -import { Node, isNodeType, isContainer } from '../interfaces/ehtag.ast'; +import { tagAbbr } from '../tag.js'; +import { Node, isNodeType, isContainer } from '../interfaces/ehtag.ast.js'; export function renderText(node: Node | readonly Node[]): string { if (!('type' in node)) return node.map(renderText).join('').trim(); diff --git a/src/shared/namespace-database.ts b/src/shared/namespace-database.ts index a079ba2c..6c2f3d5a 100644 --- a/src/shared/namespace-database.ts +++ b/src/shared/namespace-database.ts @@ -1,13 +1,13 @@ import fs from 'fs-extra'; import readline from 'readline'; -import type { NamespaceName, FrontMatters, NamespaceInfo, TagType, NamespaceData, Tag } from './interfaces/ehtag'; import { load, dump } from 'js-yaml'; -import { TagRecord } from './tag-record'; -import type { Database } from './database'; -import type { RawTag } from './raw-tag'; -import type { NamespaceDatabaseView } from './interfaces/database'; -import { Context } from './markdown'; import { PassThrough } from 'stream'; +import type { NamespaceName, FrontMatters, NamespaceInfo, TagType, NamespaceData, Tag } from './interfaces/ehtag.js'; +import { TagRecord } from './tag-record.js'; +import type { Database } from './database.js'; +import type { RawTag } from './raw-tag.js'; +import type { NamespaceDatabaseView } from './interfaces/database.js'; +import { Context } from './markdown/index.js'; interface TagLine { raw?: RawTag; diff --git a/src/shared/namespace.ts b/src/shared/namespace.ts index b203e913..5d19bb4f 100644 --- a/src/shared/namespace.ts +++ b/src/shared/namespace.ts @@ -1,4 +1,4 @@ -import { NamespaceName } from './interfaces/ehtag'; +import { NamespaceName } from './interfaces/ehtag.js'; const nsDic: { [k: string]: NamespaceName } = { rows: 'rows', diff --git a/src/shared/repo-info-provider.ts b/src/shared/repo-info-provider.ts index fd15fc3d..21fbdeea 100644 --- a/src/shared/repo-info-provider.ts +++ b/src/shared/repo-info-provider.ts @@ -1,5 +1,5 @@ import simpleGit from 'simple-git'; -import type { RepoInfo, Sha1Value } from './interfaces/ehtag'; +import type { RepoInfo, Sha1Value } from './interfaces/ehtag.js'; export interface RepoInfoProvider { head(): Promise | RepoInfo['head']; diff --git a/src/shared/tag-record.ts b/src/shared/tag-record.ts index 015bba22..6c526e5f 100644 --- a/src/shared/tag-record.ts +++ b/src/shared/tag-record.ts @@ -1,8 +1,8 @@ -import type { Tag, TagType } from './interfaces/ehtag'; -import { Cell } from './cell'; -import type { NamespaceDatabaseView } from './interfaces/database'; -import type { Context } from './markdown'; -import { RawTag } from './raw-tag'; +import type { Tag, TagType } from './interfaces/ehtag.js'; +import { Cell } from './cell.js'; +import type { NamespaceDatabaseView } from './interfaces/database.js'; +import type { Context } from './markdown/index.js'; +import { RawTag } from './raw-tag.js'; const recordRegex = /^\s*(?.*?)\s*(?.*?)\s*(?.*?)\s*(?.*?)\s*(? { const tagFromEh = await getTagGroups(); diff --git a/src/tool/commands/auto-tagger/translate.ts b/src/tool/commands/auto-tagger/translate.ts index 4962b29b..256fbacb 100644 --- a/src/tool/commands/auto-tagger/translate.ts +++ b/src/tool/commands/auto-tagger/translate.ts @@ -1,11 +1,11 @@ -import { Context, parse, render } from '../../../shared/markdown'; -import type { NamespaceName, Tag } from '../../../shared/interfaces/ehtag'; -import type { RawTag } from '../../../shared/raw-tag'; -import { parseTag } from '../tag/command'; -import { command } from './command'; -import { searchEhWiki } from './lib/search-eh-wiki'; -import { Gallery, searchTag } from './lib/search-tag'; -import { translateByWiki } from './lib/translate-by-wiki'; +import { Context, parse, render } from '#shared/markdown/index'; +import type { NamespaceName, Tag } from '#shared/interfaces/ehtag'; +import type { RawTag } from '#shared/raw-tag'; +import { parseTag } from '../tag/command.js'; +import { command } from './command.js'; +import { searchEhWiki } from './lib/search-eh-wiki.js'; +import { Gallery, searchTag } from './lib/search-tag.js'; +import { translateByWiki } from './lib/translate-by-wiki.js'; async function findJaInGalleryTitles(raw: RawTag, galleries: Gallery[], page = 1): Promise { let found; diff --git a/src/tool/commands/create-release/index.ts b/src/tool/commands/create-release/index.ts index e9bd3e81..162ea740 100644 --- a/src/tool/commands/create-release/index.ts +++ b/src/tool/commands/create-release/index.ts @@ -4,15 +4,15 @@ import { program } from 'commander'; import fs from 'fs-extra'; import { gzip } from 'pako'; import path from 'path'; -import { parseNamespace } from '../../../shared/namespace'; +import { parseNamespace } from '#shared/namespace'; import { promisify } from 'util'; -import { Database } from '../../../shared/database'; -import { getTagGroups, normalizeTag } from '../../../shared/ehentai'; -import { NamespaceName, RepoData, TagType } from '../../../shared/interfaces/ehtag'; -import { Context, Logger } from '../../../shared/markdown'; -import type { RawTag } from '../../../shared/raw-tag'; -import { action } from '../../utils'; -import pako from './pako'; +import { Database } from '#shared/database'; +import { getTagGroups, normalizeTag } from '#shared/ehentai/index'; +import { NamespaceName, RepoData, TagType } from '#shared/interfaces/ehtag'; +import { Context, Logger } from '#shared/markdown/index'; +import type { RawTag } from '#shared/raw-tag'; +import { action } from '../../utils.js'; +import pako from './pako.js'; async function logFile(file: string): Promise { console.log(`Created: ${file} (${(await fs.stat(file)).size} bytes)`); diff --git a/src/tool/commands/github-actions/delete-releases.ts b/src/tool/commands/github-actions/delete-releases.ts index 7aae5f5e..93f778ca 100644 --- a/src/tool/commands/github-actions/delete-releases.ts +++ b/src/tool/commands/github-actions/delete-releases.ts @@ -1,9 +1,9 @@ import path from 'path'; import Git from 'simple-git'; import { Octokit } from '@octokit/rest'; -import { action } from '../../utils'; -import { command } from './command'; -import { lsRemoteTags } from './utils'; +import { action } from '../../utils.js'; +import { command } from './command.js'; +import { lsRemoteTags } from './utils.js'; import type { OptionValues } from 'commander'; class Main { diff --git a/src/tool/commands/github-actions/generate-token.ts b/src/tool/commands/github-actions/generate-token.ts index 39e8036d..4e927d17 100644 --- a/src/tool/commands/github-actions/generate-token.ts +++ b/src/tool/commands/github-actions/generate-token.ts @@ -1,7 +1,7 @@ import { Octokit } from '@octokit/rest'; import { createAppAuth, StrategyOptions } from '@octokit/auth-app'; -import { ensureEnv, action } from '../../utils'; -import { command } from './command'; +import { ensureEnv, action } from '../../utils.js'; +import { command } from './command.js'; import type { OptionValues } from 'commander'; async function main(envName?: string): Promise { diff --git a/src/tool/commands/github-actions/index.ts b/src/tool/commands/github-actions/index.ts index 049fb920..53989dd3 100644 --- a/src/tool/commands/github-actions/index.ts +++ b/src/tool/commands/github-actions/index.ts @@ -1,3 +1,3 @@ -import './delete-releases'; -import './generate-token'; -import './set-release-note'; +import './delete-releases.js'; +import './generate-token.js'; +import './set-release-note.js'; diff --git a/src/tool/commands/github-actions/set-release-note.ts b/src/tool/commands/github-actions/set-release-note.ts index ca941a54..170beaa6 100644 --- a/src/tool/commands/github-actions/set-release-note.ts +++ b/src/tool/commands/github-actions/set-release-note.ts @@ -1,9 +1,9 @@ -import { action } from '../../utils'; +import { action } from '../../utils.js'; import SimpleGit from 'simple-git'; -import { command } from './command'; -import { GitRepoInfoProvider } from '../../../shared/repo-info-provider'; -import { Sha1Value } from '../../../shared/interfaces/ehtag'; -import { lsRemoteTags } from './utils'; +import { command } from './command.js'; +import { GitRepoInfoProvider } from '#shared/repo-info-provider'; +import { Sha1Value } from '#shared/interfaces/ehtag'; +import { lsRemoteTags } from './utils.js'; import type { OptionValues } from 'commander'; function compareInfo(before: string, after: string): string { diff --git a/src/tool/commands/github-actions/utils.ts b/src/tool/commands/github-actions/utils.ts index 2d66c1cf..013baca0 100644 --- a/src/tool/commands/github-actions/utils.ts +++ b/src/tool/commands/github-actions/utils.ts @@ -1,5 +1,5 @@ import type { SimpleGit } from 'simple-git'; -import { Sha1Value } from '../../../shared/interfaces/ehtag'; +import { Sha1Value } from '#shared/interfaces/ehtag'; interface GitTag { sha: Sha1Value; diff --git a/src/tool/commands/parse.ts b/src/tool/commands/parse.ts index aa39ba2b..b80cb657 100644 --- a/src/tool/commands/parse.ts +++ b/src/tool/commands/parse.ts @@ -1,10 +1,10 @@ import { program } from 'commander'; -import { TagRecord } from '../../shared/tag-record'; -import { Database } from '../../shared/database'; -import { Context } from '../../shared/markdown'; -import { Cell } from '../../shared/cell'; -import { parseNamespace } from '../../shared/namespace'; -import type { NamespaceName, TagType } from '../../shared/interfaces/ehtag'; +import { TagRecord } from '#shared/tag-record'; +import { Database } from '#shared/database'; +import { Context } from '#shared/markdown/index'; +import { Cell } from '#shared/cell'; +import { parseNamespace } from '#shared/namespace'; +import type { NamespaceName, TagType } from '#shared/interfaces/ehtag'; const parse = program .command('parse') diff --git a/src/tool/commands/tag/check.ts b/src/tool/commands/tag/check.ts index c5e5796a..ed26ead5 100644 --- a/src/tool/commands/tag/check.ts +++ b/src/tool/commands/tag/check.ts @@ -1,7 +1,7 @@ -import { NamespaceName } from '../../../shared/interfaces/ehtag'; -import { normalizeTag } from '../../../shared/ehentai'; -import type { RawTag } from '../../../shared/raw-tag'; -import { command, parseTag, formatTag } from './command'; +import { NamespaceName } from '#shared/interfaces/ehtag'; +import { normalizeTag } from '#shared/ehentai/index'; +import type { RawTag } from '#shared/raw-tag'; +import { command, parseTag, formatTag } from './command.js'; function print(tag: [NamespaceName, RawTag]): void { console.log( diff --git a/src/tool/commands/tag/command.ts b/src/tool/commands/tag/command.ts index 7ee4b1af..70fed5fb 100644 --- a/src/tool/commands/tag/command.ts +++ b/src/tool/commands/tag/command.ts @@ -1,10 +1,11 @@ import { program } from 'commander'; -import type { NamespaceName } from '../../../shared/interfaces/ehtag'; -import type { RawTag } from '../../../shared/raw-tag'; -import { parseTag as parseTagRaw } from '../../../shared/tag'; -import type { Tag } from '../../../shared/ehentai'; -import clc from 'cli-color'; import escapeRegexp from 'escape-string-regexp'; +import clc from 'cli-color'; +import type { NamespaceName } from '#shared/interfaces/ehtag'; +import type { RawTag } from '#shared/raw-tag'; +import { parseTag as parseTagRaw } from '#shared/tag'; +import type { Tag } from '#shared/ehentai/index'; + export { Command } from 'commander'; export const command = program.command('tag').description('用于处理标签的相关工具'); diff --git a/src/tool/commands/tag/desc.ts b/src/tool/commands/tag/desc.ts index 1f08bf1f..e05dbf2b 100644 --- a/src/tool/commands/tag/desc.ts +++ b/src/tool/commands/tag/desc.ts @@ -1,8 +1,8 @@ import type { AxiosError } from 'axios'; -import type { Tag } from '../../../shared/interfaces/ehtag'; -import { normalizeTag } from '../../../shared/ehentai'; -import { get } from '../../../shared/ehentai/http'; -import { command, parseTag, formatTag } from './command'; +import type { Tag } from '#shared/interfaces/ehtag'; +import { normalizeTag } from '#shared/ehentai/index'; +import { get } from '#shared/ehentai/http/index'; +import { command, parseTag, formatTag } from './command.js'; command .command('desc <[namespace:]tag>') diff --git a/src/tool/commands/tag/index.ts b/src/tool/commands/tag/index.ts index 45090382..54a08c18 100644 --- a/src/tool/commands/tag/index.ts +++ b/src/tool/commands/tag/index.ts @@ -1,3 +1,3 @@ -import './check'; -import './search'; -import './desc'; +import './check.js'; +import './search.js'; +import './desc.js'; diff --git a/src/tool/commands/tag/search.ts b/src/tool/commands/tag/search.ts index 9b2013ea..91ec8df9 100644 --- a/src/tool/commands/tag/search.ts +++ b/src/tool/commands/tag/search.ts @@ -1,6 +1,6 @@ import clc from 'cli-color'; -import { suggestTag } from '../../../shared/ehentai'; -import { command, parseTag, formatTag } from './command'; +import { suggestTag } from '#shared/ehentai/index'; +import { command, parseTag, formatTag } from './command.js'; command .command('search <[namespace:]tag>') diff --git a/src/tool/index.ts b/src/tool/index.ts index aee789d4..5f27320b 100644 --- a/src/tool/index.ts +++ b/src/tool/index.ts @@ -1,10 +1,8 @@ -import '../shared/init'; - -import './commands/auto-tagger'; -import './commands/create-release'; -import './commands/parse'; -import './commands/tag'; -import './commands/github-actions'; +import './commands/auto-tagger/index.js'; +import './commands/create-release/index.js'; +import './commands/parse.js'; +import './commands/tag/index.js'; +import './commands/github-actions/index.js'; import { program } from 'commander'; program.parse(); diff --git a/src/tool/tsconfig.json b/src/tool/tsconfig.json index bcdcb133..e183722d 100644 --- a/src/tool/tsconfig.json +++ b/src/tool/tsconfig.json @@ -1,8 +1,9 @@ { "extends": "../tsconfig.json", "compilerOptions": { - "target": "ES2018", - "module": "CommonJS", + "target": "ES2021", + "module": "ESNext", + "moduleResolution": "Node", "outDir": "../../dist", "lib": ["ES2018"] }, diff --git a/src/tool/utils.ts b/src/tool/utils.ts index d701c8fa..f3a850ea 100644 --- a/src/tool/utils.ts +++ b/src/tool/utils.ts @@ -1,4 +1,4 @@ -import type { Sha1Value } from '../shared/interfaces/ehtag'; +import type { Sha1Value } from '#shared/interfaces/ehtag'; import * as actionsCore from '@actions/core'; import * as actionsExec from '@actions/exec'; @@ -11,7 +11,7 @@ export function ensureEnv(name: string, parser?: (s: string) => T): T { return parser(env); } -class GithubAction { +class _GithubAction { /** 触发工作流程的提交 SHA。 例如 ffac537e6cbbf934b08745a378932722df287a53。 */ get sha(): Sha1Value { return ensureEnv('GITHUB_SHA') as Sha1Value; @@ -43,12 +43,12 @@ class GithubAction { } } -Object.defineProperties(GithubAction.prototype, Object.getOwnPropertyDescriptors(actionsCore)); -Object.defineProperties(GithubAction.prototype, Object.getOwnPropertyDescriptors(actionsExec)); +Object.defineProperties(_GithubAction.prototype, Object.getOwnPropertyDescriptors(actionsCore)); +Object.defineProperties(_GithubAction.prototype, Object.getOwnPropertyDescriptors(actionsExec)); type ActionsCore = typeof actionsCore; type ActionsExec = typeof actionsExec; // eslint-disable-next-line @typescript-eslint/no-empty-interface -interface GithubAction extends ActionsCore, ActionsExec {} +type GithubAction = _GithubAction & ActionsCore & ActionsExec; -export const action = new GithubAction(); +export const action = new _GithubAction() as GithubAction; diff --git a/src/tsconfig.json b/src/tsconfig.json index 458cdd6a..3a8ac756 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -13,8 +13,11 @@ "module": "ESNext", "moduleResolution": "node", "importHelpers": true, - "target": "es6", - "types": ["node", "bluebird-global"], + "target": "ES2020", + + "paths": { + "#*": ["./*"] + }, "strict": true, "noImplicitReturns": true, diff --git a/src/server/e2e.test.ts b/test/server/e2e.test.js similarity index 93% rename from src/server/e2e.test.ts rename to test/server/e2e.test.js index 2cc2f201..9cbbbe1d 100644 --- a/src/server/e2e.test.ts +++ b/test/server/e2e.test.js @@ -1,27 +1,30 @@ +// @ts-check +import { jest } from '@jest/globals'; import { Test } from '@nestjs/testing'; import supertest from 'supertest'; -import { AppModule } from './app/app.module'; -import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; -import type * as fastify from 'fastify'; -import { setupSwagger, enableCors } from './setup'; +import { FastifyAdapter } from '@nestjs/platform-fastify'; import { HttpStatus } from '@nestjs/common'; +import { AppModule } from '#server/app/app.module'; +import { setupSwagger, enableCors } from '#server/setup'; jest.setTimeout(30_000); describe('AppController (e2e)', () => { - let app: NestFastifyApplication; + /** @type {import('@nestjs/platform-fastify').NestFastifyApplication} */ + let app; beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }).compile(); - app = moduleFixture.createNestApplication(new FastifyAdapter(), {}); + app = moduleFixture.createNestApplication(new FastifyAdapter(), {}); enableCors(app); setupSwagger(app); await app.init(); - const adapter = app.getHttpAdapter() as unknown as FastifyAdapter; - await adapter.getInstance().ready(); + /** @type {FastifyAdapter} */ + const adapter = app.getHttpAdapter(); + await adapter.getInstance().ready(); }); afterAll(async () => { @@ -33,7 +36,7 @@ describe('AppController (e2e)', () => { .head('/database') .expect(HttpStatus.OK) .expect((res) => expect(res.header).toHaveProperty('etag')) - .expect(undefined as unknown as string); + .expect(undefined); }, 3000); it('HEAD /database ETag: [ETag]', async () => { @@ -41,10 +44,10 @@ describe('AppController (e2e)', () => { .head('/database') .expect(HttpStatus.OK) .expect((res) => expect(res.header).toHaveProperty('etag')) - .expect(undefined as unknown as string); + .expect(undefined); const _2 = await supertest(app.getHttpServer()) .head('/database') - .set('If-None-Match', (_.header as Record)['etag']) + .set('If-None-Match', _.header['etag']) .expect(HttpStatus.NOT_MODIFIED); }); @@ -102,7 +105,7 @@ describe('AppController (e2e)', () => { .head('/database/rows/female') .expect(HttpStatus.OK) .expect((res) => expect(res.header).toHaveProperty('etag')) - .expect(undefined as unknown as string); + .expect(undefined); }); it('GET /database/rows/female?format=text.json', async () => { diff --git a/test/server/jest.config.js b/test/server/jest.config.js new file mode 100644 index 00000000..51b624f8 --- /dev/null +++ b/test/server/jest.config.js @@ -0,0 +1,24 @@ +import path from 'node:path'; +import url from 'node:url'; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); + +/** @typedef {import('ts-jest')} */ +/** @type {import('@jest/types').Config.InitialOptions} */ +const config = { + rootDir: path.resolve(__dirname, '../..'), + roots: ['/'], + setupFilesAfterEnv: [path.resolve(__dirname, './setup-jest.js')], + testEnvironment: 'node', + testRegex: 'test/server/.+(\\.test|\\.spec)\\.js$', + transform: {}, + + collectCoverage: true, + coverageProvider: 'v8', + + moduleNameMapper: { + '^#(.*)$': '/dist/$1.js', + }, +}; + +export default config; diff --git a/src/server/setup-jest.ts b/test/server/setup-jest.js similarity index 83% rename from src/server/setup-jest.ts rename to test/server/setup-jest.js index 67f149a8..e3a1f27f 100644 --- a/src/server/setup-jest.ts +++ b/test/server/setup-jest.js @@ -1,4 +1,3 @@ -import '../shared/init'; import { toMatchOneOf, toMatchShapeOf } from 'jest-to-match-shape-of'; expect.extend({ diff --git a/test/server/tsconfig.json b/test/server/tsconfig.json new file mode 100644 index 00000000..ae727fed --- /dev/null +++ b/test/server/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../src/server/tsconfig.json", + "compilerOptions": { + "types": ["node", "jest", "jest-to-match-shape-of"] + }, + "include": ["**/*.ts"] +} diff --git a/tsconfig.json b/tsconfig.json index 92e0bb4b..fc059db1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ { "path": "./src/browser/tsconfig.json" }, { "path": "./src/browser/tsconfig.worker.json" }, { "path": "./src/server/tsconfig.json" }, - { "path": "./src/server/tsconfig.test.json" }, { "path": "./src/tool/tsconfig.json" } + { "path": "./test/server/tsconfig.json" }, ] } diff --git a/yarn.lock b/yarn.lock index 45708e6d..bbabfe52 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,7 +36,20 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@angular-devkit/architect@0.1400.2": +"@angular-builders/custom-webpack@^14.0.0": + version "14.0.0" + resolved "https://registry.npmmirror.com/@angular-builders/custom-webpack/-/custom-webpack-14.0.0.tgz#46f11621fdb919df77c6e38f338906e0690145fa" + integrity sha512-6ky8rdW9k2FNcbUeGub2uxZq+wrF2OxIkQtFaPuQ8GKD94YYQHl+AdJT2pnvfoFs4OqsHh1APdwFD5gF4WKi5Q== + dependencies: + "@angular-devkit/architect" ">=0.1400.0 < 0.1500.0" + "@angular-devkit/build-angular" "^14.0.0" + "@angular-devkit/core" "^14.0.0" + lodash "^4.17.15" + ts-node "^10.0.0" + tsconfig-paths "^3.9.0" + webpack-merge "^5.7.3" + +"@angular-devkit/architect@0.1400.2", "@angular-devkit/architect@>=0.1400.0 < 0.1500.0": version "0.1400.2" resolved "https://registry.npmmirror.com/@angular-devkit/architect/-/architect-0.1400.2.tgz#acd6502687ccb47ed35c1712c1c094351c6a3daf" integrity sha512-L+QIaN17M2APAJ4v3eVOSohqhnqTloDjT4omdaPA9XZpob+WQ6+ALCvMuEczCRrGBskXiOsBgXeyMjGBtq1+pw== @@ -44,7 +57,7 @@ "@angular-devkit/core" "14.0.2" rxjs "6.6.7" -"@angular-devkit/build-angular@^14.0.2": +"@angular-devkit/build-angular@^14.0.0", "@angular-devkit/build-angular@^14.0.2": version "14.0.2" resolved "https://registry.npmmirror.com/@angular-devkit/build-angular/-/build-angular-14.0.2.tgz#1841ad5ee29eca7c6eafa38c37d8d926a291bf40" integrity sha512-oVjF+Q9lw1Gk93z7zIGiv4mxiyDmYPKtW4xLCL38ccCiSwunzG5/hayvmtJB+wasKznCU+DpxeQXR/Q1qwGlEw== @@ -134,7 +147,7 @@ rxjs "6.6.7" source-map "0.7.3" -"@angular-devkit/core@14.0.2": +"@angular-devkit/core@14.0.2", "@angular-devkit/core@^14.0.0": version "14.0.2" resolved "https://registry.npmmirror.com/@angular-devkit/core/-/core-14.0.2.tgz#47f62a57cf36a2e102188a89ae00f5e5a05d837d" integrity sha512-lT875LhgO+23HvjUmuCZomH/0ivetzo8xsaT+7YM8SeUpmjsNTpTA/xNAQ4uD4JGscsJeCKsGT/zJIwPAAe6vQ== @@ -1279,6 +1292,13 @@ resolved "https://registry.npmmirror.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmmirror.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@csstools/postcss-color-function@^1.1.0": version "1.1.0" resolved "https://registry.npmmirror.com/@csstools/postcss-color-function/-/postcss-color-function-1.1.0.tgz#229966327747f58fbe586de35daa139db3ce1e5d" @@ -1666,6 +1686,14 @@ resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": version "0.3.13" resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" @@ -2120,6 +2148,26 @@ resolved "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.npmmirror.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmmirror.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmmirror.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.npmmirror.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + "@types/babel__core@^7.1.14": version "7.1.19" resolved "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" @@ -2153,18 +2201,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bluebird-global@~3.5.13": - version "3.5.13" - resolved "https://registry.npmmirror.com/@types/bluebird-global/-/bluebird-global-3.5.13.tgz#8fee8f1075501e9b8bb56fc0539753c38ecdc8df" - integrity sha512-jmq47VdRYy8KPjXDlJ6zO5Ie+l5j0X2fGdSbfCS3mGdM93MTy50dh/EfltIv/QD15hCYTY+0lm/C0Bou1tPYnQ== - dependencies: - "@types/bluebird" "*" - -"@types/bluebird@*": - version "3.5.36" - resolved "https://registry.npmmirror.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652" - integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q== - "@types/body-parser@*": version "1.19.2" resolved "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" @@ -2720,7 +2756,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^8.0.0, acorn-walk@^8.2.0: +acorn-walk@^8.0.0, acorn-walk@^8.1.1, acorn-walk@^8.2.0: version "8.2.0" resolved "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== @@ -2878,6 +2914,11 @@ are-we-there-yet@^3.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmmirror.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3107,11 +3148,6 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -bluebird@~3.7.2: - version "3.7.2" - resolved "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - body-parser@1.20.0: version "1.20.0" resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" @@ -3328,9 +3364,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001349: - version "1.0.30001356" - resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001356.tgz#cbf5fe7b33f90962bfbca532212ea478d4ec9de8" - integrity sha512-/30854bktMLhxtjieIxsrJBfs2gTM1pel6MXKF3K+RdIVJZcsn2A2QdhsuR4/p9+R204fZw0zCBBhktX8xWuyQ== + version "1.0.30001357" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001357.tgz#dec7fc4158ef6ad24690d0eec7b91f32b8cb1b5d" + integrity sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg== chalk@3.0.0, chalk@^3.0.0: version "3.0.0" @@ -3683,6 +3719,11 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + critters@0.0.16: version "0.0.16" resolved "https://registry.npmmirror.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93" @@ -3695,7 +3736,14 @@ critters@0.0.16: postcss "^8.3.7" pretty-bytes "^5.3.0" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.npmmirror.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3931,6 +3979,11 @@ diff-sequences@^28.1.1: resolved "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6" integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4071,6 +4124,11 @@ entities@^2.0.0: resolved "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.3.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656" + integrity sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg== + entities@~3.0.1: version "3.0.1" resolved "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" @@ -4292,11 +4350,16 @@ escape-string-regexp@^2.0.0: resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escape-string-regexp@^4.0.0, escape-string-regexp@~4.0.0: +escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@~5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + escodegen@^1.8.1: version "1.14.3" resolved "https://registry.npmmirror.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -4905,7 +4968,7 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: dependencies: minipass "^3.0.0" -fs-monkey@1.0.3: +fs-monkey@^1.0.3: version "1.0.3" resolved "https://registry.npmmirror.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== @@ -6469,7 +6532,7 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.npmmirror.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -6547,11 +6610,11 @@ media-typer@0.3.0: integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^3.4.1, memfs@^3.4.3: - version "3.4.4" - resolved "https://registry.npmmirror.com/memfs/-/memfs-3.4.4.tgz#e8973cd8060548916adcca58a248e7805c715e89" - integrity sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA== + version "3.4.6" + resolved "https://registry.npmmirror.com/memfs/-/memfs-3.4.6.tgz#74097983d27c82b973665885dc75f27a65174510" + integrity sha512-rH9mjopto6Wkr7RFuH9l9dk3qb2XGOcYKr7xMhaYqfzuJqOqhRrcFvfD7JMuPj6SLmPreh5+6eAuv36NFAU+Mw== dependencies: - fs-monkey "1.0.3" + fs-monkey "^1.0.3" memoizee@^0.4.15: version "0.4.15" @@ -6728,9 +6791,9 @@ minipass-sized@^1.0.3: minipass "^3.0.0" minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6: - version "3.1.6" - resolved "https://registry.npmmirror.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + version "3.3.3" + resolved "https://registry.npmmirror.com/minipass/-/minipass-3.3.3.tgz#fd1f0e6c06449c10dadda72618b59c00f3d6378d" + integrity sha512-N0BOsdFAlNRfmwMhjAsLVWOk7Ljmeb39iqFlsV1At+jqRhSUP9yeof8FyJu4imaJiSUp8vQebWD/guZwGQC8iA== dependencies: yallist "^4.0.0" @@ -7286,11 +7349,18 @@ parse5@^5.0.0: resolved "https://registry.npmmirror.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== -parse5@^6.0.1, parse5@~6.0.0: +parse5@^6.0.1: version "6.0.1" resolved "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@~7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a" + integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== + dependencies: + entities "^4.3.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -8066,6 +8136,13 @@ resolve-from@^5.0.0: resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-typescript-plugin@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/resolve-typescript-plugin/-/resolve-typescript-plugin-1.2.0.tgz#411271a1661b7ce050d2fff51d9ee66311ffa78f" + integrity sha512-f0tu3fDdKcSmbgpLDNBKiMYPPG7D19tYCnph9B7GIlMMIWnbiLjAqqPXZVeO3POQSNF7ZYK4Ox+Gmvo116ERWQ== + dependencies: + tslib "2.3.1" + resolve-url-loader@5.0.0: version "5.0.0" resolved "https://registry.npmmirror.com/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz#ee3142fb1f1e0d9db9524d539cfa166e9314f795" @@ -8417,14 +8494,14 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -simple-git@~3.7.1: - version "3.7.1" - resolved "https://registry.npmmirror.com/simple-git/-/simple-git-3.7.1.tgz#cb85c59da4da3d69792d206dd28cfbd803941fac" - integrity sha512-+Osjtsumbtew2y9to0pOYjNzSIr4NkKGBg7Po5SUtjQhaJf2QBmiTX/9E9cv9rmc7oUiSGFIB9e7ys5ibnT9+A== +simple-git@~3.8.0: + version "3.8.0" + resolved "https://registry.npmmirror.com/simple-git/-/simple-git-3.8.0.tgz#d93500f3d792cec365420c80ddc6cb782edf737d" + integrity sha512-nbR1PufcbvCaW90CiAXC1mM7OnEqLzjSOnySnq7Sd2kcVG6GxSa+DhxhFmCgxLv4kWCKmZagkCZSjfNAQTZwaw== dependencies: "@kwsites/file-exists" "^1.1.1" "@kwsites/promise-deferred" "^1.1.1" - debug "^4.3.3" + debug "^4.3.4" sirv@^1.0.7: version "1.0.19" @@ -8973,6 +9050,25 @@ ts-jest@~28.0.5: semver "7.x" yargs-parser "^21.0.1" +ts-node@^10.0.0: + version "10.8.1" + resolved "https://registry.npmmirror.com/ts-node/-/ts-node-10.8.1.tgz#ea2bd3459011b52699d7e88daa55a45a1af4f066" + integrity sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tsconfig-paths-webpack-plugin@3.5.2: version "3.5.2" resolved "https://registry.npmmirror.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz#01aafff59130c04a8c4ebc96a3045c43c376449a" @@ -9001,6 +9097,11 @@ tsconfig-paths@~4.0.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.3.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tslib@2.4.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.0, tslib@~2.4.0: version "2.4.0" resolved "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" @@ -9182,6 +9283,11 @@ uuid@8.3.2, uuid@^8.3.2: resolved "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -9339,7 +9445,7 @@ webpack-dev-server@4.9.0: webpack-dev-middleware "^5.3.1" ws "^8.4.2" -webpack-merge@5.8.0: +webpack-merge@5.8.0, webpack-merge@^5.7.3: version "5.8.0" resolved "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== @@ -9544,6 +9650,11 @@ yargs@^17.2.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"