diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index d675fbc..2367ad3 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -custom: ["https://wtto00.github.io/sponsor/"] \ No newline at end of file +custom: ['https://wtto00.github.io/sponsor/'] diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0fbbc15..6d6d402 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,19 +1,19 @@ -name: Lint - -on: - pull_request: - branches: - - main - -jobs: - Lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3.1.0 - with: - node-version: 20 - cache: "npm" - - run: npm ci - - run: npm run lint +name: Lint + +on: + pull_request: + branches: + - main + +jobs: + Lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3.1.0 + with: + node-version: 20 + cache: 'npm' + - run: npm ci + - run: npm run lint diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fcf56d5..36b9250 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,34 +1,34 @@ -name: "Publish" -on: - push: - tags: - - "v*" - -jobs: - Release: - runs-on: ubuntu-latest - steps: - - name: Release - uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - draft: true - generate_release_notes: true - - Publish: - needs: Release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3.1.0 - with: - node-version: 20 - cache: "npm" - - run: npm ci - - - name: Publish to Visual Studio Marketplace - uses: HaaLeo/publish-vscode-extension@v1 - with: - pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} - registryUrl: https://marketplace.visualstudio.com +name: 'Publish' +on: + push: + tags: + - 'v*' + +jobs: + Release: + runs-on: ubuntu-latest + steps: + - name: Release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + draft: true + generate_release_notes: true + + Publish: + needs: Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3.1.0 + with: + node-version: 20 + cache: 'npm' + - run: npm ci + + - name: Publish to Visual Studio Marketplace + uses: HaaLeo/publish-vscode-extension@v1 + with: + pat: ${{ secrets.VS_MARKETPLACE_TOKEN }} + registryUrl: https://marketplace.visualstudio.com diff --git a/.gitignore b/.gitignore index 46f5462..076fe35 100644 --- a/.gitignore +++ b/.gitignore @@ -133,3 +133,6 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# husky +.husky diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..3b2ce05 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 120, + "singleQuote": true, + "semi": false, + "trailingComma": "all", + "arrowParens": "always" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3ac9aeb..c0a2258 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,5 @@ { - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "dbaeumer.vscode-eslint" - ] + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": ["dbaeumer.vscode-eslint"] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 670d6e6..1210201 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,32 +3,26 @@ // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}" - }, - { - "name": "Extension Tests", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" - ], - "outFiles": [ - "${workspaceFolder}/out/test/**/*.js" - ], - "preLaunchTask": "${defaultBuildTask}" - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": ["--extensionDevelopmentPath=${workspaceFolder}"], + "outFiles": ["${workspaceFolder}/out/**/*.js"], + "preLaunchTask": "${defaultBuildTask}" + }, + { + "name": "Extension Tests", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" + ], + "outFiles": ["${workspaceFolder}/out/test/**/*.js"], + "preLaunchTask": "${defaultBuildTask}" + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 30bf8c2..ffeaf91 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ // Place your settings in this file to overwrite default and user settings. { - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - }, - // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" -} \ No newline at end of file + "files.exclude": { + "out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "out": true // set this to false to include "out" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3b17e53..078ff7e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,20 +1,20 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format { - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] } diff --git a/README.md b/README.md index 7511059..06a0585 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ labels: - bug - abcd assignees: - - "@wtto00" + - '@wtto00' - wtto00 issue_number: 24 --- diff --git a/eslint.config.mjs b/eslint.config.mjs index e9ac58e..ae04d3a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,27 +1,35 @@ -import globals from "globals"; -import tseslint from "typescript-eslint"; +import globals from 'globals' +import tseslint from 'typescript-eslint' -import path from "path"; -import { fileURLToPath } from "url"; -import { FlatCompat } from "@eslint/eslintrc"; -import pluginJs from "@eslint/js"; +import path from 'path' +import { fileURLToPath } from 'url' +import { FlatCompat } from '@eslint/eslintrc' +import pluginJs from '@eslint/js' // mimic CommonJS variables -- not needed if using CommonJS -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ baseDirectory: __dirname, recommendedConfig: pluginJs.configs.recommended }); +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: pluginJs.configs.recommended, +}) -const tslintConfig = tseslint.config({ - files: ["src/**/*.ts"], - extends: [tseslint.configs.eslintRecommended, ...tseslint.configs.stylisticTypeChecked], - languageOptions: { - parserOptions: { - project: "tsconfig.json", +export default [ + { + languageOptions: { + globals: globals.node, + parserOptions: { + project: 'tsconfig.json', + }, }, }, - rules: { - "no-void": "off", + ...compat.extends('standard'), + tseslint.configs.eslintRecommended, + ...tseslint.configs.stylisticTypeChecked, + { + rules: { + 'no-void': 'off', + 'space-before-function-paren': 'off', + }, }, -}); - -export default [{ languageOptions: { globals: globals.node } }, ...compat.extends("standard"), ...tslintConfig]; +] diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 09c02c7..fbb8a19 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -1,28 +1,28 @@ -{ - "getPostContent": "Get content of the blog article", - "requestAuth": "Request Github authorization", - "unauthorized": "Unauthorized access", - "getRepository": "Get blog repository", - "createIssue": "Creating issue", - "createSuccess": "Issue creation successful", - "viewInBrowser": "View in browser", - "updateIssue": "Updating issue", - "updateSuccess": "Updated Issue successfully", - "syncIssue": "Syncing issue", - "syncSuccess": "Synchronized issue successfully", - - "noFileOpened": "No open files", - "currentNotMD": "The current file is not of the Markdown type", - "fileNotFound": "File not found: ", - - "titleEmpty": "The title cannot be empty", - "unkonwnIssue": "Unknown issue, please set the issue_number.", - "createFail": "Failed to create issue", - "updateFail": "Failed to update issue", - "syncFail": "Failed to get issue", - - "getRepositoryFail": "Failed to retrieve the list of repositories", - "noRepository": "You have not created a GitHub repository yet", - "blogRepository": "Repository of blog", - "slectRepository": "Please select the repository for the blog." -} +{ + "getPostContent": "Get content of the blog article", + "requestAuth": "Request Github authorization", + "unauthorized": "Unauthorized access", + "getRepository": "Get blog repository", + "createIssue": "Creating issue", + "createSuccess": "Issue creation successful", + "viewInBrowser": "View in browser", + "updateIssue": "Updating issue", + "updateSuccess": "Updated Issue successfully", + "syncIssue": "Syncing issue", + "syncSuccess": "Synchronized issue successfully", + + "noFileOpened": "No open files", + "currentNotMD": "The current file is not of the Markdown type", + "fileNotFound": "File not found: ", + + "titleEmpty": "The title cannot be empty", + "unkonwnIssue": "Unknown issue, please set the issue_number.", + "createFail": "Failed to create issue", + "updateFail": "Failed to update issue", + "syncFail": "Failed to get issue", + + "getRepositoryFail": "Failed to retrieve the list of repositories", + "noRepository": "You have not created a GitHub repository yet", + "blogRepository": "Repository of blog", + "slectRepository": "Please select the repository for the blog." +} diff --git a/l10n/bundle.l10n.zh-cn.json b/l10n/bundle.l10n.zh-cn.json index 60b8a72..72f29e7 100644 --- a/l10n/bundle.l10n.zh-cn.json +++ b/l10n/bundle.l10n.zh-cn.json @@ -1,28 +1,28 @@ -{ - "getPostContent": "获取博客文章内容", - "requestAuth": "请求Github授权", - "unauthorized": "未获得授权", - "getRepository": "获取博客仓库", - "createIssue": "正在创建Issue", - "createSuccess": "创建Issue成功", - "viewInBrowser": "前往浏览器查看", - "updateIssue": "正在更新Issue", - "updateSuccess": "更新Issue成功", - "syncIssue": "正在同步issue", - "syncSuccess": "同步Issue成功", - - "noFileOpened": "没有打开的文件", - "currentNotMD": "当前文件不是Markdown类型", - "fileNotFound": "没有找到文件:", - - "titleEmpty": "标题不能为空", - "unkonwnIssue": "未知的Issue,请设置issue_number", - "createFail": "创建Issue失败", - "updateFail": "更新Issue失败", - "syncFail": "获取Issue失败", - - "getRepositoryFail": "获取仓库列表失败", - "noRepository": "您还没有创建Github仓库", - "blogRepository": "博客仓库", - "slectRepository": "请选择博客的仓库" -} +{ + "getPostContent": "获取博客文章内容", + "requestAuth": "请求Github授权", + "unauthorized": "未获得授权", + "getRepository": "获取博客仓库", + "createIssue": "正在创建Issue", + "createSuccess": "创建Issue成功", + "viewInBrowser": "前往浏览器查看", + "updateIssue": "正在更新Issue", + "updateSuccess": "更新Issue成功", + "syncIssue": "正在同步issue", + "syncSuccess": "同步Issue成功", + + "noFileOpened": "没有打开的文件", + "currentNotMD": "当前文件不是Markdown类型", + "fileNotFound": "没有找到文件:", + + "titleEmpty": "标题不能为空", + "unkonwnIssue": "未知的Issue,请设置issue_number", + "createFail": "创建Issue失败", + "updateFail": "更新Issue失败", + "syncFail": "获取Issue失败", + + "getRepositoryFail": "获取仓库列表失败", + "noRepository": "您还没有创建Github仓库", + "blogRepository": "博客仓库", + "slectRepository": "请选择博客的仓库" +} diff --git a/lint-staged.config.mjs b/lint-staged.config.mjs new file mode 100644 index 0000000..3f2e9f9 --- /dev/null +++ b/lint-staged.config.mjs @@ -0,0 +1,4 @@ +export default { + '*': ['prettier --write --ignore-unknown'], + 'src/**/*.ts': [() => 'tsc --noEmit', 'eslint --cache --fix'], +} diff --git a/package-lock.json b/package-lock.json index a567716..136aa2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,10 @@ "eslint-plugin-promise": "^6.1.1", "glob": "^10.3.12", "globals": "^15.0.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", "mocha": "^10.4.0", + "prettier": "^3.2.5", "typescript": "^5.4.5", "typescript-eslint": "^7.6.0" }, @@ -991,6 +994,18 @@ "node": ">=6" } }, + "node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1327,6 +1342,87 @@ "node": ">= 6" } }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", @@ -1390,6 +1486,21 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", @@ -2318,6 +2429,35 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", @@ -2537,6 +2677,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -2565,6 +2717,18 @@ "node": ">=8" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz", @@ -2865,6 +3029,30 @@ "node": ">= 6" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmmirror.com/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "dev": true, + "bin": { + "husky": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.1.tgz", @@ -3197,6 +3385,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz", @@ -3394,6 +3594,15 @@ "immediate": "~3.0.5" } }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.0.tgz", @@ -3403,6 +3612,141 @@ "uc.micro": "^2.0.0" } }, + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", @@ -3434,6 +3778,135 @@ "node": ">=10" } }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lru-cache": { "version": "10.2.0", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.2.0.tgz", @@ -3466,6 +3939,12 @@ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", @@ -3488,6 +3967,18 @@ "node": ">=8.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", @@ -3654,6 +4145,33 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", @@ -3759,6 +4277,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmmirror.com/open/-/open-8.4.2.tgz", @@ -3901,6 +4434,18 @@ "node": ">=8.6" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -3919,6 +4464,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4150,6 +4710,52 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz", @@ -4160,6 +4766,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", @@ -4400,6 +5012,46 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4414,6 +5066,15 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", @@ -4561,6 +5222,18 @@ "node": ">=0.10.0" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5222,6 +5895,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", diff --git a/package.json b/package.json index e785e6a..b0a057f 100644 --- a/package.json +++ b/package.json @@ -121,9 +121,11 @@ "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "pretest": "npm run compile && npm run lint", - "lint": "eslint src/*.ts", - "lint:fix": "eslint --fix src/*.ts", - "test": "node ./out/test/runTest.js" + "format": "prettier . --write --ignore-unknown", + "lint": "eslint --color --cache src/*.ts", + "lint:fix": "npm run lint -- --fix", + "test": "node ./out/test/runTest.js", + "prepare": "husky && echo npx lint-staged > .husky/pre-commit" }, "devDependencies": { "@eslint/eslintrc": "^3.0.2", @@ -141,7 +143,10 @@ "eslint-plugin-promise": "^6.1.1", "glob": "^10.3.12", "globals": "^15.0.0", + "husky": "^9.0.11", + "lint-staged": "^15.2.2", "mocha": "^10.4.0", + "prettier": "^3.2.5", "typescript": "^5.4.5", "typescript-eslint": "^7.6.0" }, diff --git a/src/commands.ts b/src/commands.ts index 817f16c..466eb6a 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -8,9 +8,9 @@ import { initL10n } from './i10n' import * as l10n from '@vscode/l10n' export interface CommandParmas { - uri?: vscode.Uri; - credentials: Credentials; - statusBarItem: vscode.StatusBarItem; + uri?: vscode.Uri + credentials: Credentials + statusBarItem: vscode.StatusBarItem } export class Command { @@ -20,18 +20,18 @@ export class Command { github?: Github - constructor (context: vscode.ExtensionContext) { + constructor(context: vscode.ExtensionContext) { this.#context = context this.#credentials = new Credentials() this.statusBarItem = initStatusBar(this.#context.subscriptions) } - async init () { + async init() { await this.#credentials.initialize(this.#context) initL10n() } - async prepare (uri: vscode.Uri) { + async prepare(uri: vscode.Uri) { this.statusBarItem.text = `$(sync~spin) ${l10n.t('getPostContent')}...` const file = new FileUtil(uri) diff --git a/src/credentials.ts b/src/credentials.ts index 86ca4e7..8eccfa5 100644 --- a/src/credentials.ts +++ b/src/credentials.ts @@ -1,65 +1,65 @@ -import * as vscode from 'vscode' -import * as Octokit from '@octokit/rest' - -const GITHUB_AUTH_PROVIDER_ID = 'github' -// The GitHub Authentication Provider accepts the scopes described here: -// https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/ -const SCOPES = ['repo'] - -export class Credentials { - private octokit: Octokit.Octokit | undefined - - async initialize (context: vscode.ExtensionContext): Promise { - this.registerListeners(context) - await this.setOctokit() - } - - private async setOctokit () { - /** - * By passing the `createIfNone` flag, a numbered badge will show up on the accounts activity bar icon. - * An entry for the sample extension will be added under the menu to sign in. This allows quietly - * prompting the user to sign in. - * */ - const session = await vscode.authentication.getSession(GITHUB_AUTH_PROVIDER_ID, SCOPES, { createIfNone: false }) - - if (session) { - this.octokit = new Octokit.Octokit({ - auth: session.accessToken - }) - - return - } - - this.octokit = undefined - } - - registerListeners (context: vscode.ExtensionContext): void { - /** - * Sessions are changed when a user logs in or logs out. - */ - context.subscriptions.push( - vscode.authentication.onDidChangeSessions(async (e) => { - if (e.provider.id === GITHUB_AUTH_PROVIDER_ID) { - await this.setOctokit() - } - }) - ) - } - - async getOctokit (): Promise { - if (this.octokit) { - return this.octokit - } - - /** - * When the `createIfNone` flag is passed, a modal dialog will be shown asking the user to sign in. - * Note that this can throw if the user clicks cancel. - */ - const session = await vscode.authentication.getSession(GITHUB_AUTH_PROVIDER_ID, SCOPES, { createIfNone: true }) - this.octokit = new Octokit.Octokit({ - auth: session.accessToken - }) - - return this.octokit - } -} +import * as vscode from 'vscode' +import * as Octokit from '@octokit/rest' + +const GITHUB_AUTH_PROVIDER_ID = 'github' +// The GitHub Authentication Provider accepts the scopes described here: +// https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/ +const SCOPES = ['repo'] + +export class Credentials { + private octokit: Octokit.Octokit | undefined + + async initialize(context: vscode.ExtensionContext): Promise { + this.registerListeners(context) + await this.setOctokit() + } + + private async setOctokit() { + /** + * By passing the `createIfNone` flag, a numbered badge will show up on the accounts activity bar icon. + * An entry for the sample extension will be added under the menu to sign in. This allows quietly + * prompting the user to sign in. + * */ + const session = await vscode.authentication.getSession(GITHUB_AUTH_PROVIDER_ID, SCOPES, { createIfNone: false }) + + if (session) { + this.octokit = new Octokit.Octokit({ + auth: session.accessToken + }) + + return + } + + this.octokit = undefined + } + + registerListeners(context: vscode.ExtensionContext): void { + /** + * Sessions are changed when a user logs in or logs out. + */ + context.subscriptions.push( + vscode.authentication.onDidChangeSessions(async (e) => { + if (e.provider.id === GITHUB_AUTH_PROVIDER_ID) { + await this.setOctokit() + } + }) + ) + } + + async getOctokit(): Promise { + if (this.octokit) { + return this.octokit + } + + /** + * When the `createIfNone` flag is passed, a modal dialog will be shown asking the user to sign in. + * Note that this can throw if the user clicks cancel. + */ + const session = await vscode.authentication.getSession(GITHUB_AUTH_PROVIDER_ID, SCOPES, { createIfNone: true }) + this.octokit = new Octokit.Octokit({ + auth: session.accessToken + }) + + return this.octokit + } +} diff --git a/src/extension.ts b/src/extension.ts index a1709b5..6998332 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode' import { Command } from './commands' -export async function activate (context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext) { console.log('Extension "github-issue-blog" is now active!') const command = new Command(context) @@ -14,6 +14,6 @@ export async function activate (context: vscode.ExtensionContext) { context.subscriptions.push(_createIssue, _updateIssue, _syncIssue) } -export function deactivate () { +export function deactivate() { // do nothing } diff --git a/src/file.ts b/src/file.ts index 6e430a4..5f2e914 100644 --- a/src/file.ts +++ b/src/file.ts @@ -4,33 +4,37 @@ import * as matter from 'gray-matter' import * as l10n from '@vscode/l10n' export interface FileInfo { - path: string; - isUntitled?: boolean; + path: string + isUntitled?: boolean } export interface MatterData { - title?: string; - labels?: string[]; - assignees?: string[]; - issue_number?: number; + title?: string + labels?: string[] + assignees?: string[] + issue_number?: number } export interface IssueData { - content: string; - data: MatterData; + content: string + data: MatterData } export class FileUtil { issueData: IssueData uri: vscode.Uri - constructor (uri: vscode.Uri) { + constructor(uri: vscode.Uri) { this.uri = uri ?? vscode.window.activeTextEditor?.document.uri if (!uri) { // from command - if (!vscode.window.activeTextEditor?.document) throw Error(l10n.t('noFileOpened')) + if (!vscode.window.activeTextEditor?.document) { + throw Error(l10n.t('noFileOpened')) + } - if (vscode.window.activeTextEditor.document.languageId !== 'markdown') throw Error(l10n.t('currentNotMD')) + if (vscode.window.activeTextEditor.document.languageId !== 'markdown') { + throw Error(l10n.t('currentNotMD')) + } this.issueData = matter(vscode.window.activeTextEditor.document.getText()) return diff --git a/src/github.ts b/src/github.ts index f83c569..19e028e 100644 --- a/src/github.ts +++ b/src/github.ts @@ -1,143 +1,146 @@ -import * as vscode from 'vscode' -import * as Octokit from '@octokit/rest' -import { FileUtil } from './file' -import * as l10n from '@vscode/l10n' - -export interface RepoInfo { - owner: string; - repo: string; -} - -export interface GithubProps { - octokit: Octokit.Octokit; - file: FileUtil; - repo: RepoInfo; -} - -export class Github { - octokit: Octokit.Octokit - file: FileUtil - repo: RepoInfo - - constructor (props: GithubProps) { - this.octokit = props.octokit - this.file = props.file - this.repo = props.repo - } - - #checkTitle () { - const { title = '' } = this.file.issueData.data || {} - if (!title) { - void this.file.updateMDContent({ title: '' }) - throw Error(l10n.t('titleEmpty')) - } - } - - #checkId () { - const { issue_number: issueNumber } = this.file.issueData.data || {} - if (!issueNumber) { - void this.file.updateMDContent({ issue_number: 0 }) - throw Error(l10n.t('unkonwnIssue')) - } - } - - #getAssignees (assignees: string[]) { - return assignees - .map((assignee) => (assignee.startsWith('@') ? assignee.substring(1) : assignee)) - .filter((assignee) => assignee) - } - - async createIssue () { - const { content, data = {} } = this.file.issueData - const { title = '', labels = [], assignees = [] } = data - this.#checkTitle() - - const res = await this.octokit.rest.issues.create({ - owner: this.repo.owner, - repo: this.repo.repo, - title, - body: content, - labels: labels.filter((label) => label), - assignees: this.#getAssignees(assignees) - }) - if (!res.data) throw Error(l10n.t('createFail')) - const number = res.data.number - void this.file.updateMDContent({ issue_number: number }) - return res.data.html_url - } - - async updateIssue () { - const { content, data = {} } = this.file.issueData - const { issue_number: issueNumber = 0, title, labels = [], assignees = [] } = data - this.#checkId() - const res = await this.octokit.rest.issues.update({ - owner: this.repo.owner, - repo: this.repo.repo, - issue_number: issueNumber, - title, - body: content, - labels: labels.filter((label) => label), - assignees: this.#getAssignees(assignees) - }) - if (!res.data) throw Error(l10n.t('updateFail')) - void this.file.updateMDContent({}) - return res.data.html_url - } - - async syncIssue () { - const { data = {} } = this.file.issueData - const { issue_number: issueNumber = 0 } = data - this.#checkId() - const res = await this.octokit.rest.issues.get({ - owner: this.repo.owner, - repo: this.repo.repo, - issue_number: issueNumber - }) - if (!res.data) throw Error(l10n.t('syncFail')) - void this.file.updateMDContent( - { - title: res.data.title, - issue_number: issueNumber, - labels: res.data.labels - .map((label) => (typeof label === 'string' ? label : label.name!)) - .filter((label) => label), - assignees: res.data.assignees?.map((assignee) => `@${assignee.login}`) - }, - res.data.body ?? '' - ) - } - - async getIssueList () { - const res = await this.octokit.rest.issues.listForRepo({ - owner: this.repo.owner, - repo: this.repo.repo - }) - console.log('getIssueList', res.data) - } -} - -export async function getRepo (octokit: Octokit.Octokit): Promise { - const configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration() - let repository: string = configuration.get('github-issue-blog.repo') ?? '' - if (!repository) { - const res = await octokit.rest.repos.listForAuthenticatedUser() - const repoList = res.data - if (!repoList) throw Error(l10n.t('getRepositoryFail')) - - if (repoList.length === 0) throw Error(l10n.t('noRepository')) - - const selectedItem = await vscode.window.showQuickPick( - repoList.map((item) => ({ label: item.full_name, description: item.html_url })), - { - title: l10n.t('blogRepository'), - placeHolder: l10n.t('slectRepository') - } - ) - if (!selectedItem) throw Error(l10n.t('slectRepository')) - - repository = selectedItem.label - void configuration.update('github-issue-blog.repo', repository) - } - const [owner, repo] = repository.split('/') - return { owner, repo } -} +import * as vscode from 'vscode' +import * as Octokit from '@octokit/rest' +import { FileUtil } from './file' +import * as l10n from '@vscode/l10n' + +export interface RepoInfo { + owner: string + repo: string +} + +export interface GithubProps { + octokit: Octokit.Octokit + file: FileUtil + repo: RepoInfo +} + +export class Github { + octokit: Octokit.Octokit + file: FileUtil + repo: RepoInfo + + constructor(props: GithubProps) { + this.octokit = props.octokit + this.file = props.file + this.repo = props.repo + } + + #checkTitle() { + const { title = '' } = this.file.issueData.data || {} + if (!title) { + void this.file.updateMDContent({ title: '' }) + throw Error(l10n.t('titleEmpty')) + } + } + + #checkId() { + const { issue_number: issueNumber } = this.file.issueData.data || {} + if (!issueNumber) { + void this.file.updateMDContent({ issue_number: 0 }) + throw Error(l10n.t('unkonwnIssue')) + } + } + + #getAssignees(assignees: string[]) { + return assignees + .map((assignee) => (assignee.startsWith('@') ? assignee.substring(1) : assignee)) + .filter((assignee) => assignee) + } + + async createIssue() { + const { content, data = {} } = this.file.issueData + const { title = '', labels = [], assignees = [] } = data + this.#checkTitle() + + const res = await this.octokit.rest.issues.create({ + owner: this.repo.owner, + repo: this.repo.repo, + title, + body: content, + labels: labels.filter((label) => label), + assignees: this.#getAssignees(assignees) + }) + if (!res.data) throw Error(l10n.t('createFail')) + const number = res.data.number + void this.file.updateMDContent({ issue_number: number }) + return res.data.html_url + } + + async updateIssue() { + const { content, data = {} } = this.file.issueData + const { issue_number: issueNumber = 0, title, labels = [], assignees = [] } = data + this.#checkId() + const res = await this.octokit.rest.issues.update({ + owner: this.repo.owner, + repo: this.repo.repo, + issue_number: issueNumber, + title, + body: content, + labels: labels.filter((label) => label), + assignees: this.#getAssignees(assignees) + }) + if (!res.data) throw Error(l10n.t('updateFail')) + void this.file.updateMDContent({}) + return res.data.html_url + } + + async syncIssue() { + const { data = {} } = this.file.issueData + const { issue_number: issueNumber = 0 } = data + this.#checkId() + const res = await this.octokit.rest.issues.get({ + owner: this.repo.owner, + repo: this.repo.repo, + issue_number: issueNumber + }) + if (!res.data) throw Error(l10n.t('syncFail')) + void this.file.updateMDContent( + { + title: res.data.title, + issue_number: issueNumber, + labels: res.data.labels + .map((label) => (typeof label === 'string' ? label : label.name!)) + .filter((label) => label), + assignees: res.data.assignees?.map((assignee) => `@${assignee.login}`) + }, + res.data.body ?? '' + ) + } + + async getIssueList() { + const res = await this.octokit.rest.issues.listForRepo({ + owner: this.repo.owner, + repo: this.repo.repo + }) + console.log('getIssueList', res.data) + } +} + +export async function getRepo(octokit: Octokit.Octokit): Promise { + const configuration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration() + let repository: string = configuration.get('github-issue-blog.repo') ?? '' + if (!repository) { + const res = await octokit.rest.repos.listForAuthenticatedUser() + const repoList = res.data + if (!repoList) throw Error(l10n.t('getRepositoryFail')) + + if (repoList.length === 0) throw Error(l10n.t('noRepository')) + + const selectedItem = await vscode.window.showQuickPick( + repoList.map((item) => ({ + label: item.full_name, + description: item.html_url + })), + { + title: l10n.t('blogRepository'), + placeHolder: l10n.t('slectRepository') + } + ) + if (!selectedItem) throw Error(l10n.t('slectRepository')) + + repository = selectedItem.label + void configuration.update('github-issue-blog.repo', repository) + } + const [owner, repo] = repository.split('/') + return { owner, repo } +} diff --git a/src/i10n.ts b/src/i10n.ts index bc157a7..b23e8a9 100644 --- a/src/i10n.ts +++ b/src/i10n.ts @@ -1,14 +1,14 @@ -import * as l10n from '@vscode/l10n' -import { resolve } from 'path' -import * as vscode from 'vscode' - -export function initL10n () { - let lPath = vscode.l10n.uri?.fsPath - if (!lPath) { - const uri = vscode.Uri.file(resolve(__dirname, '../l10n/bundle.l10n.json')) - lPath = uri.fsPath - } - l10n.config({ - fsPath: lPath - }) -} +import * as l10n from '@vscode/l10n' +import { resolve } from 'path' +import * as vscode from 'vscode' + +export function initL10n() { + let lPath = vscode.l10n.uri?.fsPath + if (!lPath) { + const uri = vscode.Uri.file(resolve(__dirname, '../l10n/bundle.l10n.json')) + lPath = uri.fsPath + } + l10n.config({ + fsPath: lPath + }) +} diff --git a/src/statusBar.ts b/src/statusBar.ts index fcb83e4..5aa3988 100644 --- a/src/statusBar.ts +++ b/src/statusBar.ts @@ -1,7 +1,7 @@ -import * as vscode from 'vscode' - -export function initStatusBar (subscriptions: vscode.ExtensionContext['subscriptions']) { - const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0) - subscriptions.push(statusBarItem) - return statusBarItem -} +import * as vscode from 'vscode' + +export function initStatusBar(subscriptions: vscode.ExtensionContext['subscriptions']) { + const statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0) + subscriptions.push(statusBarItem) + return statusBarItem +} diff --git a/src/test/runTest.ts b/src/test/runTest.ts index 93a4441..dbbbe73 100644 --- a/src/test/runTest.ts +++ b/src/test/runTest.ts @@ -1,23 +1,23 @@ -import * as path from 'path'; +import * as path from 'path' -import { runTests } from '@vscode/test-electron'; +import { runTests } from '@vscode/test-electron' async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../'); + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, '../../') - // The path to test runner - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './suite/index'); + // The path to test runner + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, './suite/index') - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error('Failed to run tests', err); - process.exit(1); - } + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }) + } catch (err) { + console.error('Failed to run tests', err) + process.exit(1) + } } -main(); +main() diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts index 4ca0ab4..101bd6d 100644 --- a/src/test/suite/extension.test.ts +++ b/src/test/suite/extension.test.ts @@ -1,15 +1,15 @@ -import * as assert from 'assert'; +import * as assert from 'assert' // You can import and use all API from the 'vscode' module // as well as import your extension to test it -import * as vscode from 'vscode'; +import * as vscode from 'vscode' // import * as myExtension from '../../extension'; suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); + vscode.window.showInformationMessage('Start all tests.') - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); -}); + test('Sample test', () => { + assert.strictEqual(-1, [1, 2, 3].indexOf(5)) + assert.strictEqual(-1, [1, 2, 3].indexOf(0)) + }) +}) diff --git a/src/test/suite/index.ts b/src/test/suite/index.ts index bcf9173..4172b85 100644 --- a/src/test/suite/index.ts +++ b/src/test/suite/index.ts @@ -1,40 +1,40 @@ -import * as path from 'path'; -import * as Mocha from 'mocha'; -import * as glob from 'glob'; +import * as path from 'path' +import * as Mocha from 'mocha' +import * as glob from 'glob' export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - color: true - }); + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd', + color: true + }) - const testsRoot = path.resolve(__dirname, '..'); + const testsRoot = path.resolve(__dirname, '..') - return new Promise((c, e) => { - const testFiles = new glob.Glob("**/**.test.js", { cwd: testsRoot }); - const testFileStream = testFiles.stream(); + return new Promise((resolve, reject) => { + const testFiles = new glob.Glob('**/**.test.js', { cwd: testsRoot }) + const testFileStream = testFiles.stream() - testFileStream.on("data", (file) => { - mocha.addFile(path.resolve(testsRoot, file)); - }); - testFileStream.on("error", (err) => { - e(err); - }); - testFileStream.on("end", () => { - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }); - }); + testFileStream.on('data', (file) => { + mocha.addFile(path.resolve(testsRoot, file)) + }) + testFileStream.on('error', (err) => { + reject(err) + }) + testFileStream.on('end', () => { + try { + // Run the mocha test + mocha.run((failures) => { + if (failures > 0) { + reject(new Error(`${failures} tests failed.`)) + } else { + resolve() + } + }) + } catch (err) { + console.error(err) + reject(err) + } + }) + }) } diff --git a/tsconfig.json b/tsconfig.json index e27aba0..e67e86c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,16 @@ { - "compilerOptions": { - "module": "commonjs", - "moduleResolution": "Node10", - "target": "ES2020", - "outDir": "out", - "lib": [ - "ES2020" - ], - "sourceMap": true, - "rootDir": "src", - "strict": true /* enable all strict type-checking options */ - /* Additional Checks */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - } + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "Node10", + "target": "ES2020", + "outDir": "out", + "lib": ["ES2020"], + "sourceMap": true, + "rootDir": "src", + "strict": true /* enable all strict type-checking options */ + /* Additional Checks */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + } }