diff --git a/.gitignore b/.gitignore index 3c3629e..0714c6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +database.sqlite diff --git a/package.json b/package.json index ced2889..4019ccc 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "puppeteer": "20.1.0", "puppeteer-extra": "3.3.6", "puppeteer-extra-plugin-stealth": "2.11.2", + "rimraf": "^3.0.2", "tapable": "^2.2.1" } } diff --git a/packages/dingtalk-plugin/index.mjs b/packages/dingtalk-plugin/index.mjs index c91e836..dda45c2 100644 --- a/packages/dingtalk-plugin/index.mjs +++ b/packages/dingtalk-plugin/index.mjs @@ -17,7 +17,9 @@ export default class DingtalkPlugin { collectedMessageList[0].dingtalkRequestBody.text.content += `\n${dayjs(collectedMessageList[0].insertedTime).format('MM-DD HH:mm:ss')}\n\n【geekgeekrun】` requestDingtalkNotify( _this.dingtalkAccessToken, JSON.stringify(collectedMessageList[0].dingtalkRequestBody) - ) + ).then(res => res.json()).then((res) => { + console.log('[DingtalkPlugin] Response: ', res) + }, () => void 0) } else { requestDingtalkNotify( _this.dingtalkAccessToken, JSON.stringify((createTextMessage( @@ -25,7 +27,9 @@ export default class DingtalkPlugin { return `${it.dingtalkRequestBody.text.content}\n${dayjs(it.insertedTime).format('MM-DD HH:mm:ss')}\n` }).join('-----\n') + '\n【geekgeekrun】' )).dingtalkRequestBody) - ) + ).then(res => res.json()).then((res) => { + console.log('[DingtalkPlugin] Response: ', res) + }, () => void 0) } collectedMessageList.length = 0 sendQueueTimer = setTimeout(sendMergedMessage, interval) diff --git a/packages/geek-auto-start-chat-with-boss/index.mjs b/packages/geek-auto-start-chat-with-boss/index.mjs index 7468db6..8d37672 100644 --- a/packages/geek-auto-start-chat-with-boss/index.mjs +++ b/packages/geek-auto-start-chat-with-boss/index.mjs @@ -113,8 +113,7 @@ export async function mainLoop (hooks) { hooks.pageLoaded?.call() let userInfoResponse = await userInfoPromise - hooks.userInfoResponse?.call(userInfoResponse) - + await hooks.userInfoResponse?.promise(userInfoResponse) if (userInfoResponse.code !== 0) { autoStartChatEventBus.emit('LOGIN_STATUS_INVALID', { userInfoResponse @@ -176,68 +175,105 @@ export async function mainLoop (hooks) { try { const { targetJobElProxy, targetJobIndex } = await new Promise(async (resolve, reject) => { - // job list - const recommendJobListElProxy = await page.$('.job-list-container .rec-job-list') - - let jobListData = await page.evaluate( - ` - document.querySelector('.job-recommend-main')?.__vue__?.jobList - ` - ) - // when disable company allow list, we will believe that the first one in the list is your expect job. - let targetJobIndex = enableCompanyAllowList ? jobListData.findIndex( - it => !blockBossNotNewChat.has(it.encryptBossId) && [...expectCompanySet].find(name => it.brandName.includes(name)) - ) : jobListData.findIndex( - it => !blockBossNotNewChat.has(it.encryptBossId) - ) - - let hasReachLastPage = false - - while (targetJobIndex < 0 && !hasReachLastPage) { - // fetch new - const recommendJobListElBBox = await recommendJobListElProxy.boundingBox() - const windowInnerHeight = await page.evaluate('window.innerHeight') - await page.mouse.move( - recommendJobListElBBox.x + recommendJobListElBBox.width / 2, - windowInnerHeight / 2 - ) - let scrolledHeight = 0 - const targetHeight = 3000 - const increase = 40 + Math.floor(30 * Math.random()) - while (scrolledHeight < targetHeight) { - scrolledHeight += increase - await page.mouse.wheel({deltaY: increase}); - await sleep(1) - } - hasReachLastPage = await page.evaluate(` - !(document.querySelector('.job-recommend-main')?.__vue__?.hasMore) - `) - if (hasReachLastPage) { - console.log(`Arrive the terminal of the job list.`) - } - - await sleep(3000) - jobListData = await page.evaluate( + try { + // job list + const recommendJobListElProxy = await page.$('.job-list-container .rec-job-list') + + let jobListData = await page.evaluate( ` document.querySelector('.job-recommend-main')?.__vue__?.jobList ` ) - targetJobIndex = jobListData.findIndex(it => !blockBossNotNewChat.has(it.encryptBossId) && [...expectCompanySet].find(name => it.brandName.includes(name))) - } + // when disable company allow list, we will believe that the first one in the list is your expect job. + let targetJobIndex = enableCompanyAllowList ? jobListData.findIndex( + it => !blockBossNotNewChat.has(it.encryptBossId) && [...expectCompanySet].find(name => it.brandName.includes(name)) + ) : jobListData.findIndex( + it => !blockBossNotNewChat.has(it.encryptBossId) + ) - if (targetJobIndex < 0 && hasReachLastPage) { - // has reach last page and not find target job - reject(new Error('CANNOT_FIND_EXCEPT_JOB')) - return - } - - const recommendJobItemList = await recommendJobListElProxy.$$('ul.rec-job-list > li') - resolve( - { - targetJobElProxy: recommendJobItemList[targetJobIndex], - targetJobIndex + let hasReachLastPage = false + + let requestNextPagePromiseWithResolver = null + page.on( + 'request', + function reqHandler (request) { + if (request.url().startsWith('https://www.zhipin.com/wapi/zpgeek/pc/recommend/job/list.json')) { + requestNextPagePromiseWithResolver = (() => { + const o = {} + o.promise = new Promise((resolve, reject) => { + o.resolve = resolve + o.reject = reject + }) + return o + })() + page.off(reqHandler) + + page.on( + 'response', + function resHandler (response) { + if (response.request() === request) { + requestNextPagePromiseWithResolver?.resolve() + page.off(resHandler) + } + } + ) + } + } + ) + + while (targetJobIndex < 0 && !hasReachLastPage) { + // fetch new + const recommendJobListElBBox = await recommendJobListElProxy.boundingBox() + const windowInnerHeight = await page.evaluate('window.innerHeight') + await page.mouse.move( + recommendJobListElBBox.x + recommendJobListElBBox.width / 2, + windowInnerHeight / 2 + ) + let scrolledHeight = 0 + const increase = 40 + Math.floor(30 * Math.random()) + + while ( + !requestNextPagePromiseWithResolver && + !hasReachLastPage + ) { + scrolledHeight += increase + await page.mouse.wheel({deltaY: increase}); + await sleep(1) + await requestNextPagePromiseWithResolver?.promise + hasReachLastPage = await page.evaluate(` + !(document.querySelector('.job-recommend-main')?.__vue__?.hasMore) + `) + if (hasReachLastPage) { + console.log(`Arrive the terminal of the job list.`) + } + } + requestNextPagePromiseWithResolver = null + + await sleep(3000) + jobListData = await page.evaluate( + ` + document.querySelector('.job-recommend-main')?.__vue__?.jobList + ` + ) + targetJobIndex = jobListData.findIndex(it => !blockBossNotNewChat.has(it.encryptBossId) && [...expectCompanySet].find(name => it.brandName.includes(name))) } - ) + + if (targetJobIndex < 0 && hasReachLastPage) { + // has reach last page and not find target job + reject(new Error('CANNOT_FIND_EXCEPT_JOB')) + return + } + + const recommendJobItemList = await recommendJobListElProxy.$$('ul.rec-job-list > li') + resolve( + { + targetJobElProxy: recommendJobItemList[targetJobIndex], + targetJobIndex + } + ) + } catch(err) { + reject(err) + } }) if (targetJobIndex >= 0) { // scroll that target element into view @@ -297,7 +333,7 @@ export async function mainLoop (hooks) { throw new Error('STARTUP_CHAT_ERROR_WITH_UNKNOWN_ERROR') } } else { - hooks.newChatStartup?.call(jobData) + await hooks.newChatStartup?.promise(jobData) blockBossNotNewChat.add(jobData.jobInfo.encryptUserId) await storeStorage(page).catch(() => void 0) diff --git a/packages/geek-auto-start-chat-with-boss/runtime-file-utils.mjs b/packages/geek-auto-start-chat-with-boss/runtime-file-utils.mjs index 311a767..dcb31e2 100644 --- a/packages/geek-auto-start-chat-with-boss/runtime-file-utils.mjs +++ b/packages/geek-auto-start-chat-with-boss/runtime-file-utils.mjs @@ -141,3 +141,7 @@ export const writeStorageFile = async (fileName, content) => { fileContent ) } + +export const getPublicDbFilePath = () => { + return path.join(storageFilePath, 'public.db') +} \ No newline at end of file diff --git a/packages/launch-bosszhipin-login-page-with-preload-extension/package-lock.json b/packages/launch-bosszhipin-login-page-with-preload-extension/package-lock.json deleted file mode 100644 index dea2a94..0000000 --- a/packages/launch-bosszhipin-login-page-with-preload-extension/package-lock.json +++ /dev/null @@ -1,351 +0,0 @@ -{ - "name": "@geekgeekrun/launch-browser-with-preload-extension", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@geekgeekrun/launch-browser-with-preload-extension", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "node-fetch": "^3.3.2", - "unzipper": "^0.10.14" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmmirror.com/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmmirror.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmmirror.com/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmmirror.com/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "engines": { - "node": "*" - } - }, - "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmmirror.com/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/packages/run-core-of-geek-auto-start-chat-with-boss/daemon-main.mjs b/packages/run-core-of-geek-auto-start-chat-with-boss/daemon-main.mjs index 1d71b57..d2b2293 100644 --- a/packages/run-core-of-geek-auto-start-chat-with-boss/daemon-main.mjs +++ b/packages/run-core-of-geek-auto-start-chat-with-boss/daemon-main.mjs @@ -41,7 +41,7 @@ function runWithDaemon () { process.exit(exitCode) return } - console.log(`[Run core daemon] Child process exit with code ${exitCode}, an internal may not be caught, and will be restarted in ${rerunInterval}ms.`) + console.log(`[Run core daemon] Child process exit with code ${exitCode}, an internal error may not be caught, and will be restarted in ${rerunInterval}ms.`) await sleep(rerunInterval) runWithDaemon() } diff --git a/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs b/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs index 84521ce..5ff4726 100644 --- a/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs +++ b/packages/run-core-of-geek-auto-start-chat-with-boss/main.mjs @@ -8,12 +8,17 @@ import fs from 'node:fs' import path from 'node:path' import { get__dirname } from '@geekgeekrun/utils/legacy-path.mjs'; import JSON5 from 'json5' -import { readConfigFile, readStorageFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import { readConfigFile, readStorageFile, getPublicDbFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' import { sleep } from '@geekgeekrun/utils/sleep.mjs' import { AUTO_CHAT_ERROR_EXIT_CODE } from './enums.mjs' +import SqlitePluginModule from '@geekgeekrun/sqlite-plugin' +const { + default: SqlitePlugin +} = SqlitePluginModule + const rerunInterval = (() => { let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL) if (isNaN(v)) { @@ -32,6 +37,7 @@ const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk. const initPlugins = (hooks) => { new DingtalkPlugin(dingTalkAccessToken).apply(hooks) + new SqlitePlugin(getPublicDbFilePath()).apply(hooks) } const main = async () => { @@ -43,8 +49,9 @@ const main = async () => { puppeteerLaunched: new SyncHook(), pageLoaded: new SyncHook(), cookieWillSet: new SyncHook(['cookies']), + userInfoResponse: new AsyncSeriesHook(['userInfo']), newChatWillStartup: new AsyncSeriesHook(['positionInfoDetail']), - newChatStartup: new SyncHook(['positionInfoDetail']), + newChatStartup: new AsyncSeriesHook(['positionInfoDetail']), noPositionFoundForCurrentJob: new SyncHook(), noPositionFoundAfterTraverseAllJob: new SyncHook(), errorEncounter: new SyncHook(['errorInfo']) @@ -68,8 +75,9 @@ const main = async () => { break } } + closeBrowserWindow?.() console.error(err) - console.log(`[Run core main] An internal is caught, and browser will be restarted in ${rerunInterval}ms.`) + console.log(`[Run core main] An internal error is caught, and browser will be restarted in ${rerunInterval}ms.`) await sleep(rerunInterval) } } @@ -78,5 +86,7 @@ const main = async () => { (async () => { try { await main() - } catch {} + } catch(err) { + console.error(err) + } })() \ No newline at end of file diff --git a/packages/run-core-of-geek-auto-start-chat-with-boss/package.json b/packages/run-core-of-geek-auto-start-chat-with-boss/package.json index cb779df..6e2eff9 100644 --- a/packages/run-core-of-geek-auto-start-chat-with-boss/package.json +++ b/packages/run-core-of-geek-auto-start-chat-with-boss/package.json @@ -14,6 +14,7 @@ "dependencies": { "@geekgeekrun/dingtalk-plugin": "workspace:*", "@geekgeekrun/geek-auto-start-chat-with-boss": "workspace:*", - "@geekgeekrun/utils": "workspace:*" + "@geekgeekrun/utils": "workspace:*", + "@geekgeekrun/sqlite-plugin": "workspace:*" } } diff --git a/packages/sqlite-plugin/.gitignore b/packages/sqlite-plugin/.gitignore new file mode 100644 index 0000000..6b0e0cf --- /dev/null +++ b/packages/sqlite-plugin/.gitignore @@ -0,0 +1,4 @@ +node_modules +src/**/*.js +src/**/*.js.map +dist diff --git a/packages/sqlite-plugin/.npmignore b/packages/sqlite-plugin/.npmignore new file mode 100644 index 0000000..e831038 --- /dev/null +++ b/packages/sqlite-plugin/.npmignore @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/packages/sqlite-plugin/package.json b/packages/sqlite-plugin/package.json new file mode 100644 index 0000000..f2f2336 --- /dev/null +++ b/packages/sqlite-plugin/package.json @@ -0,0 +1,19 @@ +{ + "name": "@geekgeekrun/sqlite-plugin", + "version": "0.0.1", + "description": "", + "main": "dist/index.js", + "dependencies": { + "cli-highlight": "^2.1.11", + "reflect-metadata": "^0.2.1", + "sqlite3": "5.1.6", + "ts-node": "^10.9.2", + "typeorm": "0.3.11", + "typescript": "^5.3.3" + }, + "scripts": { + "dev": "rimraf dist && tsc --outDir dist --watch true", + "build": "rimraf dist && tsc --outDir dist", + "postinstall": "npm run build || exit 0;" + } +} diff --git a/packages/sqlite-plugin/src/entity/BossActiveStatusRecord.ts b/packages/sqlite-plugin/src/entity/BossActiveStatusRecord.ts new file mode 100644 index 0000000..f8890dc --- /dev/null +++ b/packages/sqlite-plugin/src/entity/BossActiveStatusRecord.ts @@ -0,0 +1,17 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryGeneratedColumn } = requireTypeorm(); + +@Entity() +export class BossActiveStatusRecord { + @PrimaryGeneratedColumn() + id: number; + + @Column() + encryptBossId: string; + + @Column() + lastActiveStatus: string; + + @Column() + updateDate: Date; +} \ No newline at end of file diff --git a/packages/sqlite-plugin/src/entity/BossInfo.ts b/packages/sqlite-plugin/src/entity/BossInfo.ts new file mode 100644 index 0000000..f7eea6c --- /dev/null +++ b/packages/sqlite-plugin/src/entity/BossInfo.ts @@ -0,0 +1,20 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryColumn } = requireTypeorm(); + +@Entity() +export class BossInfo { + @PrimaryColumn() + encryptBossId: string; + + @Column() + encryptCompanyId: string; + + @Column() + name: string; + + @Column() + date: Date; + + @Column() + title: string; +} diff --git a/packages/sqlite-plugin/src/entity/BossInfoChangeLog.ts b/packages/sqlite-plugin/src/entity/BossInfoChangeLog.ts new file mode 100644 index 0000000..48173dc --- /dev/null +++ b/packages/sqlite-plugin/src/entity/BossInfoChangeLog.ts @@ -0,0 +1,17 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryGeneratedColumn } = requireTypeorm() + +@Entity() +export class BossInfoChangeLog { + @PrimaryGeneratedColumn() + id: number; + + @Column() + encryptBossId: string; + + @Column() + updateTime: Date; + + @Column() + dataAsJson: string; +} diff --git a/packages/sqlite-plugin/src/entity/ChatStartupLog.ts b/packages/sqlite-plugin/src/entity/ChatStartupLog.ts new file mode 100644 index 0000000..e451c99 --- /dev/null +++ b/packages/sqlite-plugin/src/entity/ChatStartupLog.ts @@ -0,0 +1,17 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryGeneratedColumn } = requireTypeorm() + +@Entity() +export class ChatStartupLog { + @PrimaryGeneratedColumn() + id: number; + + @Column() + encryptJobId: string; + + @Column() + encryptCurrentUserId: string; + + @Column() + date: Date; +} diff --git a/packages/sqlite-plugin/src/entity/CompanyInfo.ts b/packages/sqlite-plugin/src/entity/CompanyInfo.ts new file mode 100644 index 0000000..b8d61fd --- /dev/null +++ b/packages/sqlite-plugin/src/entity/CompanyInfo.ts @@ -0,0 +1,34 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryColumn } = requireTypeorm() + +@Entity() +export class CompanyInfo { + @PrimaryColumn() + encryptCompanyId: string; + + @Column() + name: string; + + @Column() + brandName: string; + + @Column({ + nullable: true + }) + scaleLow?: number; + + @Column({ + nullable: true + }) + scaleHeight?: number; + + @Column({ + nullable: true + }) + stageName?: string; + + @Column({ + nullable: true + }) + industryName?: string; +} diff --git a/packages/sqlite-plugin/src/entity/CompanyInfoChangeLog.ts b/packages/sqlite-plugin/src/entity/CompanyInfoChangeLog.ts new file mode 100644 index 0000000..4d226ce --- /dev/null +++ b/packages/sqlite-plugin/src/entity/CompanyInfoChangeLog.ts @@ -0,0 +1,17 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, PrimaryGeneratedColumn, Column } = requireTypeorm() + +@Entity() +export class CompanyInfoChangeLog { + @PrimaryGeneratedColumn() + id: number; + + @Column() + encryptCompanyId: string; + + @Column() + updateTime: Date; + + @Column() + dataAsJson: string; +} diff --git a/packages/sqlite-plugin/src/entity/JobInfo.ts b/packages/sqlite-plugin/src/entity/JobInfo.ts new file mode 100644 index 0000000..48562de --- /dev/null +++ b/packages/sqlite-plugin/src/entity/JobInfo.ts @@ -0,0 +1,54 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryColumn } = requireTypeorm() + +@Entity() +export class JobInfo { + @PrimaryColumn() + encryptJobId: string; + + @Column() + jobName: string; + + @Column() + positionName: string; + + @Column({ + nullable: true + }) + salaryLow?: number; + + @Column({ + nullable: true + }) + salaryHeight?: number; + + @Column({ + nullable: true + }) + salaryMonth?: number; + + @Column() + experienceName: string; + + @Column({ + nullable: true + }) + publishDate?: Date; + + @Column({ + nullable: true + }) + degreeName?: string; + + @Column() + address: string; + + @Column() + description: string; + + @Column() + encryptBossId: string; + + @Column() + encryptCompanyId: string; +} diff --git a/packages/sqlite-plugin/src/entity/JobInfoChangeLog.ts b/packages/sqlite-plugin/src/entity/JobInfoChangeLog.ts new file mode 100644 index 0000000..a90190f --- /dev/null +++ b/packages/sqlite-plugin/src/entity/JobInfoChangeLog.ts @@ -0,0 +1,17 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, PrimaryGeneratedColumn, Column } = requireTypeorm() + +@Entity() +export class JobInfoChangeLog { + @PrimaryGeneratedColumn() + id: number; + + @Column() + encryptJobId: string; + + @Column() + updateTime: Date; + + @Column() + dataAsJson: string; +} diff --git a/packages/sqlite-plugin/src/entity/UserInfo.ts b/packages/sqlite-plugin/src/entity/UserInfo.ts new file mode 100644 index 0000000..665f1f7 --- /dev/null +++ b/packages/sqlite-plugin/src/entity/UserInfo.ts @@ -0,0 +1,11 @@ +import { requireTypeorm } from "../utils/module-loader"; +const { Entity, Column, PrimaryColumn } = requireTypeorm() + +@Entity() +export class UserInfo { + @PrimaryColumn() + encryptUserId: string; + + @Column() + name: string; +} diff --git a/packages/sqlite-plugin/src/index.ts b/packages/sqlite-plugin/src/index.ts new file mode 100644 index 0000000..ff07b44 --- /dev/null +++ b/packages/sqlite-plugin/src/index.ts @@ -0,0 +1,146 @@ +import "reflect-metadata"; +import { type DataSource } from "typeorm"; +import { parseCompanyScale, parseSalary } from "./utils/parser"; +import { requireTypeorm } from "./utils/module-loader"; + +import { BossInfo } from "./entity/BossInfo"; +import { BossInfoChangeLog } from "./entity/BossInfoChangeLog"; +import { ChatStartupLog } from './entity/ChatStartupLog'; +import { CompanyInfoChangeLog } from "./entity/CompanyInfoChangeLog"; +import { CompanyInfo } from "./entity/CompanyInfo"; +import { JobInfo } from "./entity/JobInfo"; +import { JobInfoChangeLog } from "./entity/JobInfoChangeLog"; +import { BossActiveStatusRecord } from "./entity/BossActiveStatusRecord"; +import { UserInfo } from "./entity/UserInfo"; + +import sqlite3 from 'sqlite3'; +import * as cliHighlight from 'cli-highlight'; +Boolean(cliHighlight); + +function initDb(dbFilePath) { + const { DataSource } = requireTypeorm() + const appDataSource = new DataSource({ + type: "sqlite", + synchronize: true, + logging: true, + logger: "simple-console", + database: dbFilePath, + driver: sqlite3, // The important line + entities: [ + ChatStartupLog, + BossInfo, + BossInfoChangeLog, + CompanyInfo, + CompanyInfoChangeLog, + JobInfo, + JobInfoChangeLog, + BossActiveStatusRecord, + UserInfo, + ], + }); + return appDataSource.initialize(); +} + +export default class SqlitePlugin { + initPromise: Promise; + + constructor(dbFilePath) { + this.initPromise = initDb(dbFilePath); + } + + userInfo = null + + apply(hooks) { + hooks.userInfoResponse.tapPromise( + "SqlitePlugin", + async (userInfoResponse) => { + if (userInfoResponse.code !== 0) { + return; + } + const { zpData: userInfo } = userInfoResponse; + this.userInfo = userInfo + console.log(userInfo); + + const ds = await this.initPromise; + const userInfoRepository = ds.getRepository(UserInfo); + + const user = new UserInfo(); + user.encryptUserId = userInfo.encryptUserId; + user.name = userInfo.name; + + return await userInfoRepository.save(user); + } + ); + + hooks.newChatStartup.tapPromise("SqlitePlugin", async (_jobInfo) => { + console.log(_jobInfo); + const ds = await this.initPromise; + + const { bossInfo, brandComInfo, jobInfo } = _jobInfo; + + //#region boss + const boss = new BossInfo(); + boss.encryptBossId = jobInfo.encryptUserId; + boss.encryptCompanyId = brandComInfo.encryptBrandId; + boss.name = bossInfo.name; + boss.title = bossInfo.title; + boss.date = new Date(); + const bossInfoRepository = ds.getRepository(BossInfo); + await bossInfoRepository.save(boss); + //#endregion + + //#region company + const company = new CompanyInfo(); + company.encryptCompanyId = brandComInfo.encryptBrandId; + company.brandName = brandComInfo.brandName; + company.name = brandComInfo.customerBrandName; + company.industryName = brandComInfo.industryName; + company.stageName = brandComInfo.stageName; + const companyScale = parseCompanyScale(brandComInfo.scaleName) + company.scaleLow = companyScale[0] + company.scaleHeight = companyScale[1] + + const companyInfoRepository = ds.getRepository(CompanyInfo); + await companyInfoRepository.save(company); + //#endregion + + //#region job + const job = new JobInfo(); + const jobSalary = parseSalary(jobInfo.salaryDesc) + const jobUpdatePayload: JobInfo = { + address: jobInfo.address, + degreeName: jobInfo.degreeName, + description: jobInfo.postDescription, + encryptBossId: jobInfo.encryptUserId, + encryptCompanyId: brandComInfo.encryptBrandId, + encryptJobId: jobInfo.encryptId, + jobName: jobInfo.jobName, + positionName: jobInfo.positionName, + experienceName: jobInfo.experienceName, + salaryHeight: jobSalary.heigh, + salaryLow: jobSalary.low, + salaryMonth: jobSalary.month, + }; + + Object.assign(job, jobUpdatePayload); + + const jobInfoRepository = ds.getRepository(JobInfo); + await jobInfoRepository.save(job); + //#endregion + + //#region chat-startup-log + const chatStartupLog = new ChatStartupLog() + const chatStartupLogPayload: Partial = { + date: new Date(), + encryptCurrentUserId: this.userInfo.encryptUserId, + encryptJobId: jobInfo.encryptId, + } + Object.assign(chatStartupLog, chatStartupLogPayload) + + const chatStartupLogRepository = ds.getRepository(ChatStartupLog); + await chatStartupLogRepository.save(chatStartupLog); + //#endregion + return + }); + } +} diff --git a/packages/sqlite-plugin/src/utils/module-loader.ts b/packages/sqlite-plugin/src/utils/module-loader.ts new file mode 100644 index 0000000..d6e1135 --- /dev/null +++ b/packages/sqlite-plugin/src/utils/module-loader.ts @@ -0,0 +1,9 @@ +import * as path from 'node:path'; +import type typeormType from 'typeorm' +const isRunFromUi = Boolean(process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE) +const isUiDev = process.env.NODE_ENV === 'development' + +export function requireTypeorm () { + const importResult = require('typeorm') + return importResult +} \ No newline at end of file diff --git a/packages/sqlite-plugin/src/utils/parser.ts b/packages/sqlite-plugin/src/utils/parser.ts new file mode 100644 index 0000000..16544bb --- /dev/null +++ b/packages/sqlite-plugin/src/utils/parser.ts @@ -0,0 +1,67 @@ +export const parseCompanyScale = (str: string): [number| null, number | null] => { + if (!str) { + return [null, null] + } + + const betweenRangeMatchResult = str.match( + /(\d+)-(\d+)人/ + ); + if (betweenRangeMatchResult) { + const arr = [...betweenRangeMatchResult]; + arr.shift(); + return arr.map(Number) as [number, number] + } + + const gtRangeMatchResult = str.match( + /(\d+)人以上/ + ); + if (gtRangeMatchResult) { + const arr = [...gtRangeMatchResult]; + arr.shift(); + return [Number(arr[0]), null] + } + + return [null, null] +} + +export const parseSalary = (str: string): { low: null | number, heigh: null | number, month: null | number } => { + const result = { + heigh: null, + low: null, + month: null + } + if (!str) { + return result + } + + const baseMatchResult = str.match( + /([\.\d]+)-([\.\d]+)k/i + ); + if (baseMatchResult) { + const arr = [...baseMatchResult]; + arr.shift(); + Object.assign( + result, + { + low: Number(arr[0]), + heigh: Number(arr[1]), + } + ) + } + + const month = str.match( + /([\.\d]+)薪/ + ) + if (month) { + const arr = [...month]; + arr.shift(); + Object.assign( + result, + { + month: Number(arr[0]) + } + ) + } + + return result +} diff --git a/packages/sqlite-plugin/tsconfig.json b/packages/sqlite-plugin/tsconfig.json new file mode 100644 index 0000000..db7cde2 --- /dev/null +++ b/packages/sqlite-plugin/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "lib": ["ES2020"], + "target": "ES2020", + "module": "Node16", + "moduleResolution": "Node16", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": false, + }, + "exclude": ["node_modules"], +} diff --git a/packages/ui/electron-builder.yml b/packages/ui/electron-builder.yml index 599db3f..31bd619 100644 --- a/packages/ui/electron-builder.yml +++ b/packages/ui/electron-builder.yml @@ -2,6 +2,7 @@ appId: com.geekgeekrun.ui productName: GeekGeekRun directories: buildResources: build +icon: resources/icon.png files: - '!**/.vscode/*' - '!src/*' diff --git a/packages/ui/external-node-runtime-dependencies/index.cjs b/packages/ui/external-node-runtime-dependencies/index.cjs index 9a27075..c91f535 100644 --- a/packages/ui/external-node-runtime-dependencies/index.cjs +++ b/packages/ui/external-node-runtime-dependencies/index.cjs @@ -1,6 +1,5 @@ Object.assign(module.exports, { puppeteerExtra: require('puppeteer-extra'), PuppeteerExtraPluginStealth: require('puppeteer-extra-plugin-stealth'), - puppeteerManager: require('@puppeteer/browsers'), - findChromeBin: require('find-chrome-bin') + puppeteerManager: require('@puppeteer/browsers') }) diff --git a/packages/ui/external-node-runtime-dependencies/package.json b/packages/ui/external-node-runtime-dependencies/package.json index 9ade453..8cc47a8 100644 --- a/packages/ui/external-node-runtime-dependencies/package.json +++ b/packages/ui/external-node-runtime-dependencies/package.json @@ -4,8 +4,7 @@ "description": "", "main": "index.cjs", "module": "index.mjs", - "scripts": { - }, + "scripts": {}, "author": "", "license": "ISC", "dependencies": { diff --git a/packages/ui/package.json b/packages/ui/package.json index cfa2717..37fd192 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -4,6 +4,7 @@ "description": "An Electron application with Vue and TypeScript", "main": "./out/main/index.js", "author": "geekgeekrun", + "productName": "GeekGeekRun", "scripts": { "start": "electron-vite preview", "dev": "electron-vite dev", @@ -30,9 +31,11 @@ "@geekgeekrun/dingtalk-plugin": "workspace:*", "@geekgeekrun/geek-auto-start-chat-with-boss": "workspace:*", "@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension": "workspace:*", + "@geekgeekrun/sqlite-plugin": "workspace:*", "@geekgeekrun/utils": "workspace:*", "@puppeteer/browsers": "^2.0.0", "JSONStream": "^1.3.5", + "animate.css": "^4.1.1", "electron-updater": "^6.1.7", "element-plus": "^2.5.5", "find-chrome-bin": "^2.0.1", diff --git a/packages/ui/resources/icon.png b/packages/ui/resources/icon.png index cf9e8b2..a64b4c3 100644 Binary files a/packages/ui/resources/icon.png and b/packages/ui/resources/icon.png differ diff --git a/packages/ui/src/common/enums/auto-start-chat.ts b/packages/ui/src/common/enums/auto-start-chat.ts index 78cbfc0..a0e001a 100644 --- a/packages/ui/src/common/enums/auto-start-chat.ts +++ b/packages/ui/src/common/enums/auto-start-chat.ts @@ -4,5 +4,7 @@ export enum AUTO_CHAT_ERROR_EXIT_CODE { LOGIN_STATUS_INVALID = 82, ERR_INTERNET_DISCONNECTED = 83, ACCESS_IS_DENIED = 84, - PUPPETEER_IS_NOT_EXECUTABLE = 85 + PUPPETEER_IS_NOT_EXECUTABLE = 85, + AUTO_START_CHAT_DAEMON_PROCESS_SUICIDE = 86, + AUTO_START_CHAT_MAIN_PROCESS_SUICIDE = 87, } diff --git a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts index 055a157..5d286f0 100644 --- a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts +++ b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index.ts @@ -1,9 +1,11 @@ -import path from 'node:path' -import * as url from 'url' import { sleep } from '@geekgeekrun/utils/sleep.mjs' import childProcess from 'node:child_process' import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat' import { app } from 'electron' +import fs, { WriteStream } from 'node:fs' +import { pipeWriteRegardlessError } from '../utils/pipe' +import * as JSONStream from 'JSONStream' +import { initPowerSaveBlocker } from './power-saver-blocker' const rerunInterval = (() => { let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL) @@ -22,6 +24,24 @@ function runWithDaemon() { } }) + subProcessOfCore!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { + const data = raw + switch (data.type) { + case 'AUTO_START_CHAT_MAIN_PROCESS_STARTUP': { + pipeWriteRegardlessError( + subProcessOfCore!.stdio[3]! as WriteStream, + JSON.stringify({ + type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN' + }) + ) + break + } + default: { + return + } + } + }) + subProcessOfCore.once('exit', async (exitCode: number) => { if ( [...Object.values(AUTO_CHAT_ERROR_EXIT_CODE)] @@ -35,16 +55,64 @@ function runWithDaemon() { return } console.log( - `[Run core daemon] Child process exit with code ${exitCode}, an internal may not be caught, and will be restarted in ${rerunInterval}ms.` + `[Run core daemon] Child process exit with code ${exitCode}, an internal error may not be caught, and will be restarted in ${rerunInterval}ms.` ) await sleep(rerunInterval) runWithDaemon() }) } + +// suicide timer for parent and child process don't have any communication after child process spawned. +let suicideTimer: NodeJS.Timeout | null = null +const setSuicideTimer = () => + (suicideTimer = setTimeout(() => { + app.exit(AUTO_CHAT_ERROR_EXIT_CODE.AUTO_START_CHAT_DAEMON_PROCESS_SUICIDE) + }, 10000)) +const clearSuicideTimer = () => { + if (suicideTimer) { + clearTimeout(suicideTimer) + } + suicideTimer = null +} + export function runAutoChatWithDaemon() { app.dock?.hide() process.on('disconnect', () => { app.exit() }) - runWithDaemon() + setSuicideTimer() + + let pipe: null | fs.WriteStream = null + try { + pipe = fs.createWriteStream(null, { fd: 3 }) + } catch { + console.error('pipe is not available') + app.exit(1) + } + + const disposePowerSaveBlocker = initPowerSaveBlocker() + app.once('quit', disposePowerSaveBlocker) + + const pipeForRead: fs.ReadStream = fs.createReadStream(null, { fd: 3 }) + const pipeForReadWithJsonParser = pipeForRead.pipe(JSONStream.parse()) + pipeForReadWithJsonParser?.on('data', function waitForCanRun(data) { + if (data.type === 'GEEK_AUTO_START_CHAT_CAN_BE_RUN') { + pipeForReadWithJsonParser.off('data', waitForCanRun) + clearSuicideTimer() + runWithDaemon() + + // if don't call close, when kill child process, child process will ANR. + pipeForRead.close() + } + }) + process.on('SIGINT', () => { + process.exit() + }) + + pipeWriteRegardlessError( + pipe, + JSON.stringify({ + type: 'AUTO_START_CHAT_DAEMON_PROCESS_STARTUP' + }) + ) } diff --git a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/power-saver-blocker.ts b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/power-saver-blocker.ts new file mode 100644 index 0000000..f8940b5 --- /dev/null +++ b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/power-saver-blocker.ts @@ -0,0 +1,10 @@ +import { powerSaveBlocker } from 'electron' + +export const initPowerSaveBlocker = ( + type: 'prevent-app-suspension' | 'prevent-display-sleep' = 'prevent-app-suspension' +) => { + const id = powerSaveBlocker.start(type) + return function disposePowerSaveBlocker() { + return powerSaveBlocker.stop(id) + } +} diff --git a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts index 79f3f6f..74adbaf 100644 --- a/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts +++ b/packages/ui/src/main/flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index.ts @@ -1,27 +1,47 @@ import DingtalkPlugin from '@geekgeekrun/dingtalk-plugin/index.mjs' import { app } from 'electron' import { SyncHook, AsyncSeriesHook } from 'tapable' -import { readConfigFile } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import { + readConfigFile, + getPublicDbFilePath +} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' + import * as fs from 'fs' import { pipeWriteRegardlessError } from '../utils/pipe' import { getAnyAvailablePuppeteerExecutable } from '../CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable' import { sleep } from '@geekgeekrun/utils/sleep.mjs' import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../common/enums/auto-start-chat' +import * as JSONStream from 'JSONStream' + +import SqlitePluginModule from '@geekgeekrun/sqlite-plugin' +const { default: SqlitePlugin } = SqlitePluginModule + +const rerunInterval = (() => { + let v = Number(process.env.MAIN_BOSSGEEKGO_RERUN_INTERVAL) + if (isNaN(v)) { + v = 3000 + } + + return v +})() const { groupRobotAccessToken: dingTalkAccessToken } = readConfigFile('dingtalk.json') const initPlugins = (hooks) => { new DingtalkPlugin(dingTalkAccessToken).apply(hooks) + new SqlitePlugin(getPublicDbFilePath()).apply(hooks) } let isParentProcessDisconnect = false +process.once('disconnect', () => { + isParentProcessDisconnect = true +}) -export const runAutoChat = async () => { +const runAutoChat = async () => { const { initPuppeteer, mainLoop, closeBrowserWindow, autoStartChatEventBus } = await import( '@geekgeekrun/geek-auto-start-chat-with-boss/index.mjs' ) process.on('disconnect', () => { - isParentProcessDisconnect = true closeBrowserWindow() app.exit() }) @@ -62,8 +82,9 @@ export const runAutoChat = async () => { puppeteerLaunched: new SyncHook(), pageLoaded: new SyncHook(), cookieWillSet: new SyncHook(['cookies']), + userInfoResponse: new AsyncSeriesHook(['userInfo']), newChatWillStartup: new AsyncSeriesHook(['positionInfoDetail']), - newChatStartup: new SyncHook(['positionInfoDetail']), + newChatStartup: new AsyncSeriesHook(['positionInfoDetail']), noPositionFoundForCurrentJob: new SyncHook(), noPositionFoundAfterTraverseAllJob: new SyncHook(), errorEncounter: new SyncHook(['errorInfo']) @@ -89,13 +110,72 @@ export const runAutoChat = async () => { try { await mainLoop(hooks) } catch (err) { - console.log(err) - if (err instanceof Error && err.message.includes('LOGIN_STATUS_INVALID')) { - process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID) - break + if (err instanceof Error) { + if (err.message.includes('LOGIN_STATUS_INVALID')) { + process.exit(AUTO_CHAT_ERROR_EXIT_CODE.LOGIN_STATUS_INVALID) + break + } + if (err.message.includes('ERR_INTERNET_DISCONNECTED')) { + process.exit(AUTO_CHAT_ERROR_EXIT_CODE.ERR_INTERNET_DISCONNECTED) + break + } + if (err.message.includes('ACCESS_IS_DENIED')) { + process.exit(AUTO_CHAT_ERROR_EXIT_CODE.ACCESS_IS_DENIED) + break + } } - await sleep(3000) + closeBrowserWindow?.() + console.error(err) + console.log( + `[Run core main] An internal error is caught, and browser will be restarted in ${rerunInterval}ms.` + ) + await sleep(rerunInterval) } } - closeBrowserWindow() +} +// suicide timer for parent and child process don't have any communication after child process spawned. +let suicideTimer: NodeJS.Timeout | null = null +const setSuicideTimer = () => + (suicideTimer = setTimeout(() => { + app.exit(AUTO_CHAT_ERROR_EXIT_CODE.AUTO_START_CHAT_MAIN_PROCESS_SUICIDE) + }, 10000)) +const clearSuicideTimer = () => { + if (suicideTimer) { + clearTimeout(suicideTimer) + } + suicideTimer = null +} + +export const waitForProcessHandShakeAndRunAutoChat = () => { + setSuicideTimer() + + const pipeForRead: fs.ReadStream = fs.createReadStream(null, { fd: 3 }) + pipeForRead.on('error', () => { + return + }) + const pipeForReadWithJsonParser = pipeForRead.pipe(JSONStream.parse()) + pipeForReadWithJsonParser?.on('data', function waitForCanRun(data) { + if (data.type === 'GEEK_AUTO_START_CHAT_CAN_BE_RUN') { + pipeForReadWithJsonParser.off('data', waitForCanRun) + clearSuicideTimer() + runAutoChat() + + // if don't call close, when kill child process, child process will ANR. + pipeForRead.close() + } + }) + + let pipe: null | fs.WriteStream = null + try { + pipe = fs.createWriteStream(null, { fd: 3 }) + } catch { + console.error('pipe is not available') + app.exit(1) + } + pipeWriteRegardlessError( + pipe, + JSON.stringify({ + type: 'AUTO_START_CHAT_MAIN_PROCESS_STARTUP' + }) + ) } diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/app-menu.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/app-menu.ts new file mode 100644 index 0000000..881f5f4 --- /dev/null +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/app-menu.ts @@ -0,0 +1,27 @@ +import { app, Menu, MenuItemConstructorOptions, MenuItem } from 'electron' + +const isMac = process.platform === 'darwin' + +const template: (MenuItemConstructorOptions | MenuItem)[] = [ + // { role: 'appMenu' } + ...(isMac + ? [ + { + label: app.name, + submenu: [ + { role: 'about' }, + { type: 'separator' }, + { role: 'services' }, + { type: 'separator' }, + { role: 'hide' }, + { role: 'hideOthers' }, + { role: 'unhide' }, + { type: 'separator' }, + { role: 'quit' } + ] + } + ] + : []) +] +const menu = Menu.buildFromTemplate(template) +Menu.setApplicationMenu(menu) diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts similarity index 72% rename from packages/ui/src/main/flow/OPEN_SETTING_WINDOW.ts rename to packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts index 3ac0bee..01f4f7f 100644 --- a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW.ts +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/index.ts @@ -1,7 +1,8 @@ -import { app, BrowserWindow, ipcMain } from 'electron' +import { app, BrowserWindow, ipcMain, globalShortcut } from 'electron' import { electronApp, optimizer } from '@electron-toolkit/utils' -import { createMainWindow } from '../window/mainWindow' - +import { createMainWindow } from '../../window/mainWindow' +import './app-menu' +import initIpc from './ipc' export function openSettingWindow() { // TODO: singleton lock; how can we check if there is another process should run as singleton with arguments? if (!app.requestSingleInstanceLock()) { @@ -9,10 +10,12 @@ export function openSettingWindow() { app.exit(0) } + const whenReadyPromise = app.whenReady() + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. - app.whenReady().then(() => { + whenReadyPromise.then(() => { // Set app user model id for windows electronApp.setAppUserModelId('com.electron') @@ -23,10 +26,11 @@ export function openSettingWindow() { optimizer.watchWindowShortcuts(window) }) + createMainWindow() + // IPC test ipcMain.on('ping', () => console.log('pong')) - - createMainWindow() + initIpc() app.on('activate', function () { // On macOS it's common to re-create a window in the app when the @@ -44,4 +48,16 @@ export function openSettingWindow() { // In this file you can include the rest of your app"s specific main process // code. You can also put them in separate files and require them here. + + // short cut + whenReadyPromise.then(() => { + // Register a 'Command+Option+Shift+/' shortcut listener. + globalShortcut.register('Command+Option+Shift+/', () => { + console.log('Command+Option+Shift+/ is pressed') + app.exit(0) + }) + app.once('quit', () => { + globalShortcut.unregister('Command+Option+Shift+/') + }) + }) } diff --git a/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts new file mode 100644 index 0000000..7da07ac --- /dev/null +++ b/packages/ui/src/main/flow/OPEN_SETTING_WINDOW/ipc/index.ts @@ -0,0 +1,260 @@ +import { ipcMain, shell } from 'electron' + +import * as childProcess from 'node:child_process' +import { + ensureConfigFileExist, + ensureStorageFileExist, + configFileNameList, + readConfigFile, + writeConfigFile, + readStorageFile, + writeStorageFile +} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' +import { ChildProcess } from 'child_process' +import * as JSONStream from 'JSONStream' +import { checkCookieListFormat } from '../../../../common/utils/cookie' +import { getAnyAvailablePuppeteerExecutable } from '../../../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable/index' +import { sleep } from '@geekgeekrun/utils/sleep.mjs' +import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../../../common/enums/auto-start-chat' +import { mainWindow } from '../../../window/mainWindow' + +export default function initIpc () { + ipcMain.on('open-external-link', (_, link) => { + shell.openExternal(link, { + activate: true + }) + }) + + ipcMain.handle('fetch-config-file-content', async () => { + const configFileContentList = configFileNameList.map((fileName) => { + return readConfigFile(fileName) + }) + const result = { + config: {} + } + + configFileNameList.forEach((fileName, index) => { + result.config[fileName] = configFileContentList[index] + }) + + return result + }) + + ipcMain.handle('save-config-file-from-ui', async (ev, payload) => { + payload = JSON.parse(payload) + ensureConfigFileExist() + + const dingtalkConfig = readConfigFile('dingtalk.json') + dingtalkConfig.groupRobotAccessToken = payload.dingtalkRobotAccessToken + + return await Promise.all([ + writeConfigFile('dingtalk.json', dingtalkConfig), + writeConfigFile('target-company-list.json', payload.expectCompanies.split(',')) + ]) + }) + + ipcMain.handle('read-storage-file', async (ev, payload) => { + ensureStorageFileExist() + return await readStorageFile(payload.fileName) + }) + + ipcMain.handle('write-storage-file', async (ev, payload) => { + ensureStorageFileExist() + + return await writeStorageFile(payload.fileName, JSON.parse(payload.data)) + }) + + // const currentExecutablePath = app.getPath('exe') + // console.log(currentExecutablePath) + ipcMain.handle('prepare-run-geek-auto-start-chat-with-boss', async () => { + mainWindow?.webContents.send('locating-puppeteer-executable') + const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() + if (!puppeteerExecutable) { + return Promise.reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') + } + mainWindow?.webContents.send('puppeteer-executable-is-located') + }) + + let subProcessOfPuppeteer: ChildProcess | null = null + ipcMain.handle('run-geek-auto-start-chat-with-boss', async () => { + if (subProcessOfPuppeteer) { + return + } + const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() + if (!puppeteerExecutable) { + return Promise.reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') + } + const subProcessEnv = { + ...process.env, + MAIN_BOSSGEEKGO_UI_RUN_MODE: 'geekAutoStartWithBossDaemon', + PUPPETEER_EXECUTABLE_PATH: puppeteerExecutable.executablePath + } + subProcessOfPuppeteer = childProcess.spawn(process.argv[0], process.argv.slice(1), { + env: subProcessEnv, + stdio: ['inherit', 'inherit', 'inherit', 'pipe', 'ipc'] + }) + // console.log(subProcessOfPuppeteer) + return new Promise((resolve, reject) => { + subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { + const data = raw + switch (data.type) { + case 'AUTO_START_CHAT_DAEMON_PROCESS_STARTUP': { + subProcessOfPuppeteer!.stdio[3]!.write( + JSON.stringify({ + type: 'GEEK_AUTO_START_CHAT_CAN_BE_RUN' + }) + ) + break + } + case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': { + resolve(data) + break + } + case 'LOGIN_STATUS_INVALID': { + await sleep(500) + mainWindow?.webContents.send('check-boss-zhipin-cookie-file') + return + } + default: { + return + } + } + }) + + subProcessOfPuppeteer!.once('exit', (exitCode) => { + subProcessOfPuppeteer = null + if (exitCode === AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE) { + // means cannot find downloaded puppeteer + reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') + } else { + mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopped') + } + }) + }) + // TODO: + }) + + ipcMain.handle('check-dependencies', async () => { + const [anyAvailablePuppeteerExecutable] = await Promise.all([ + getAnyAvailablePuppeteerExecutable() + ]) + return { + puppeteerExecutableAvailable: !!anyAvailablePuppeteerExecutable + } + }) + + let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null + ipcMain.handle('setup-dependencies', async () => { + if (subProcessOfCheckAndDownloadDependencies) { + return + } + const subProcessEnv = { + ...process.env, + MAIN_BOSSGEEKGO_UI_RUN_MODE: 'checkAndDownloadDependenciesForInit' + } + subProcessOfCheckAndDownloadDependencies = childProcess.spawn( + process.argv[0], + process.argv.slice(1), + { + env: subProcessEnv, + stdio: [null, null, null, 'pipe', 'ipc'] + } + ) + return new Promise((resolve, reject) => { + subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on( + 'data', + (raw) => { + const data = raw + switch (data.type) { + case 'NEED_RESETUP_DEPENDENCIES': + case 'PUPPETEER_DOWNLOAD_PROGRESS': { + mainWindow?.webContents.send(data.type, data) + break + } + case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': { + console.error(data) + break + } + default: { + return + } + } + } + ) + subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => { + switch (exitCode) { + case 0: { + resolve(exitCode) + break + } + default: { + reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR') + break + } + } + subProcessOfCheckAndDownloadDependencies = null + }) + }) + }) + + ipcMain.handle('stop-geek-auto-start-chat-with-boss', async () => { + mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping') + subProcessOfPuppeteer?.kill() + }) + + let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null + ipcMain.on('launch-bosszhipin-login-page-with-preload-extension', async () => { + try { + subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() + } catch { + // + } + const subProcessEnv = { + ...process.env, + MAIN_BOSSGEEKGO_UI_RUN_MODE: 'launchBossZhipinLoginPageWithPreloadExtension', + PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutable())!.executablePath + } + subProcessOfBossZhipinLoginPageWithPreloadExtension = childProcess.spawn( + process.argv[0], + process.argv.slice(1), + { + env: subProcessEnv, + stdio: [null, null, null, 'pipe', 'ipc'] + } + ) + subProcessOfBossZhipinLoginPageWithPreloadExtension!.stdio[3]!.pipe(JSONStream.parse()).on( + 'data', + (raw) => { + const data = raw + switch (data.type) { + case 'BOSS_ZHIPIN_COOKIE_COLLECTED': { + mainWindow?.webContents.send(data.type, data) + break + } + default: { + return + } + } + } + ) + + subProcessOfBossZhipinLoginPageWithPreloadExtension!.once('exit', () => { + mainWindow?.webContents.send('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED') + subProcessOfBossZhipinLoginPageWithPreloadExtension = null + }) + }) + ipcMain.on('kill-bosszhipin-login-page-with-preload-extension', async () => { + try { + subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() + } catch { + // + } finally { + subProcessOfBossZhipinLoginPageWithPreloadExtension = null + } + }) + + ipcMain.handle('check-boss-zhipin-cookie-file', () => { + const cookies = readStorageFile('boss-cookies.json') + return checkCookieListFormat(cookies) + }) +} diff --git a/packages/ui/src/main/flow/utils/pipe.ts b/packages/ui/src/main/flow/utils/pipe.ts index 6337a0a..9e853d2 100644 --- a/packages/ui/src/main/flow/utils/pipe.ts +++ b/packages/ui/src/main/flow/utils/pipe.ts @@ -10,8 +10,12 @@ export const pipeWriteRegardlessError = async ( if (pipe && !pipeSet.has(pipe)) { pipeSet.add(pipe) pipe.on('error', (error) => { - console.log('pipe.write Error', error) + void error }) } - return pipe?.write(chunk, option, () => {}) + return pipe?.write(chunk, option, (error) => { + if (error) { + console.log('pipe.write Error', error) + } + }) } diff --git a/packages/ui/src/main/index.ts b/packages/ui/src/main/index.ts index c6e1020..370409c 100644 --- a/packages/ui/src/main/index.ts +++ b/packages/ui/src/main/index.ts @@ -1,29 +1,39 @@ -import { runAutoChat } from './flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index' -import { runAutoChatWithDaemon } from './flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index' -import { openSettingWindow } from './flow/OPEN_SETTING_WINDOW' -import { checkAndDownloadDependenciesForInit } from './flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index' -import { launchBossZhipinLoginPageWithPreloadExtension } from './flow/LAUNCH_BOSS_ZHIPIN_LOGIN_PAGE_WITH_PRELOAD_EXTENSION' - const runMode = process.env.MAIN_BOSSGEEKGO_UI_RUN_MODE -switch (runMode) { - case 'geekAutoStartWithBossMain': { - runAutoChat() - break + +;(async () => { + switch (runMode) { + case 'geekAutoStartWithBossMain': { + const { waitForProcessHandShakeAndRunAutoChat } = await import( + './flow/GEEK_AUTO_START_CHAT_WITH_BOSS_MAIN/index' + ) + waitForProcessHandShakeAndRunAutoChat() + break + } + case 'geekAutoStartWithBossDaemon': { + const { runAutoChatWithDaemon } = await import( + './flow/GEEK_AUTO_START_CHAT_WITH_BOSS_DAEMON/index' + ) + runAutoChatWithDaemon() + break + } + case 'checkAndDownloadDependenciesForInit': { + const { checkAndDownloadDependenciesForInit } = await import( + './flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index' + ) + checkAndDownloadDependenciesForInit() + break + } + case 'launchBossZhipinLoginPageWithPreloadExtension': { + const { launchBossZhipinLoginPageWithPreloadExtension } = await import( + './flow/LAUNCH_BOSS_ZHIPIN_LOGIN_PAGE_WITH_PRELOAD_EXTENSION' + ) + launchBossZhipinLoginPageWithPreloadExtension() + break + } + default: { + const { openSettingWindow } = await import('./flow/OPEN_SETTING_WINDOW/index') + openSettingWindow() + break + } } - case 'geekAutoStartWithBossDaemon': { - runAutoChatWithDaemon() - break - } - case 'checkAndDownloadDependenciesForInit': { - checkAndDownloadDependenciesForInit() - break - } - case 'launchBossZhipinLoginPageWithPreloadExtension': { - launchBossZhipinLoginPageWithPreloadExtension() - break - } - default: { - openSettingWindow() - break - } -} +})() diff --git a/packages/ui/src/main/window/mainWindow.ts b/packages/ui/src/main/window/mainWindow.ts index 4bfc48c..7a576e4 100644 --- a/packages/ui/src/main/window/mainWindow.ts +++ b/packages/ui/src/main/window/mainWindow.ts @@ -1,23 +1,6 @@ -import { BrowserWindow, ipcMain, shell } from 'electron' +import { BrowserWindow, shell } from 'electron' import path from 'path' -import * as childProcess from 'node:child_process' -import { - ensureConfigFileExist, - ensureStorageFileExist, - configFileNameList, - readConfigFile, - writeConfigFile, - readStorageFile, - writeStorageFile -} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs' -import { ChildProcess } from 'child_process' -import * as JSONStream from 'JSONStream' -import { checkCookieListFormat } from '../../common/utils/cookie' -import { getAnyAvailablePuppeteerExecutable } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/utils/puppeteer-executable/index' -import { DOWNLOAD_ERROR_EXIT_CODE } from '../flow/CHECK_AND_DOWNLOAD_DEPENDENCIES/index' -import { sleep } from '@geekgeekrun/utils/sleep.mjs' -import { AUTO_CHAT_ERROR_EXIT_CODE } from '../../common/enums/auto-start-chat' -let mainWindow: BrowserWindow | null = null +export let mainWindow: BrowserWindow | null = null export function createMainWindow(): void { // Create the browser window. @@ -56,237 +39,6 @@ export function createMainWindow(): void { mainWindow.loadFile(path.join(__dirname, '../renderer/index.html')) } - ipcMain.on('open-external-link', (_, link) => { - shell.openExternal(link, { - activate: true - }) - }) - - ipcMain.handle('fetch-config-file-content', async () => { - const configFileContentList = configFileNameList.map((fileName) => { - return readConfigFile(fileName) - }) - const result = { - config: {} - } - - configFileNameList.forEach((fileName, index) => { - result.config[fileName] = configFileContentList[index] - }) - - return result - }) - - ipcMain.handle('save-config-file-from-ui', async (ev, payload) => { - payload = JSON.parse(payload) - ensureConfigFileExist() - - const dingtalkConfig = readConfigFile('dingtalk.json') - dingtalkConfig.groupRobotAccessToken = payload.dingtalkRobotAccessToken - - return await Promise.all([ - writeConfigFile('dingtalk.json', dingtalkConfig), - writeConfigFile('target-company-list.json', payload.expectCompanies.split(',')) - ]) - }) - - ipcMain.handle('read-storage-file', async (ev, payload) => { - ensureStorageFileExist() - return await readStorageFile(payload.fileName) - }) - - ipcMain.handle('write-storage-file', async (ev, payload) => { - ensureStorageFileExist() - - return await writeStorageFile(payload.fileName, JSON.parse(payload.data)) - }) - - // const currentExecutablePath = app.getPath('exe') - // console.log(currentExecutablePath) - ipcMain.handle('prepare-run-geek-auto-start-chat-with-boss', async () => { - mainWindow?.webContents.send('locating-puppeteer-executable') - const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() - if (!puppeteerExecutable) { - return Promise.reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') - } - mainWindow?.webContents.send('puppeteer-executable-is-located') - }) - - let subProcessOfPuppeteer: ChildProcess | null = null - ipcMain.handle('run-geek-auto-start-chat-with-boss', async () => { - if (subProcessOfPuppeteer) { - return - } - const puppeteerExecutable = await getAnyAvailablePuppeteerExecutable() - if (!puppeteerExecutable) { - return Promise.reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') - } - const subProcessEnv = { - ...process.env, - MAIN_BOSSGEEKGO_UI_RUN_MODE: 'geekAutoStartWithBossDaemon', - PUPPETEER_EXECUTABLE_PATH: puppeteerExecutable.executablePath - } - subProcessOfPuppeteer = childProcess.spawn(process.argv[0], process.argv.slice(1), { - env: subProcessEnv, - stdio: [null, null, null, 'pipe', 'ipc'] - }) - console.log(subProcessOfPuppeteer) - return new Promise((resolve, reject) => { - subProcessOfPuppeteer!.stdio[3]!.pipe(JSONStream.parse()).on('data', async (raw) => { - const data = raw - switch (data.type) { - case 'GEEK_AUTO_START_CHAT_WITH_BOSS_STARTED': { - resolve(data) - break - } - case 'LOGIN_STATUS_INVALID': { - await sleep(500) - mainWindow?.webContents.send('check-boss-zhipin-cookie-file') - return - } - default: { - return - } - } - }) - - subProcessOfPuppeteer!.once('exit', (exitCode) => { - subProcessOfPuppeteer = null - if (exitCode === AUTO_CHAT_ERROR_EXIT_CODE.PUPPETEER_IS_NOT_EXECUTABLE) { - // means cannot find downloaded puppeteer - reject('NEED_TO_CHECK_RUNTIME_DEPENDENCIES') - } else { - mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopped') - } - }) - }) - // TODO: - }) - - ipcMain.handle('check-dependencies', async () => { - const [anyAvailablePuppeteerExecutable] = await Promise.all([ - getAnyAvailablePuppeteerExecutable() - ]) - return { - puppeteerExecutableAvailable: !!anyAvailablePuppeteerExecutable - } - }) - - let subProcessOfCheckAndDownloadDependencies: ChildProcess | null = null - ipcMain.handle('setup-dependencies', async () => { - if (subProcessOfCheckAndDownloadDependencies) { - return - } - const subProcessEnv = { - ...process.env, - MAIN_BOSSGEEKGO_UI_RUN_MODE: 'checkAndDownloadDependenciesForInit' - } - subProcessOfCheckAndDownloadDependencies = childProcess.spawn( - process.argv[0], - process.argv.slice(1), - { - env: subProcessEnv, - stdio: [null, null, null, 'pipe', 'ipc'] - } - ) - return new Promise((resolve, reject) => { - subProcessOfCheckAndDownloadDependencies!.stdio[3]!.pipe(JSONStream.parse()).on( - 'data', - (raw) => { - const data = raw - switch (data.type) { - case 'NEED_RESETUP_DEPENDENCIES': - case 'PUPPETEER_DOWNLOAD_PROGRESS': { - mainWindow?.webContents.send(data.type, data) - break - } - case 'PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR': { - console.error(data) - break - } - default: { - return - } - } - } - ) - subProcessOfCheckAndDownloadDependencies!.once('exit', (exitCode) => { - switch (exitCode) { - case 0: { - resolve(exitCode) - break - } - default: { - reject('PUPPETEER_DOWNLOAD_ENCOUNTER_ERROR') - break - } - } - subProcessOfCheckAndDownloadDependencies = null - }) - }) - }) - - ipcMain.handle('stop-geek-auto-start-chat-with-boss', async () => { - mainWindow?.webContents.send('geek-auto-start-chat-with-boss-stopping') - subProcessOfPuppeteer?.kill('SIGINT') - }) - - let subProcessOfBossZhipinLoginPageWithPreloadExtension: ChildProcess | null = null - ipcMain.on('launch-bosszhipin-login-page-with-preload-extension', async () => { - try { - subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() - } catch { - // - } - const subProcessEnv = { - ...process.env, - MAIN_BOSSGEEKGO_UI_RUN_MODE: 'launchBossZhipinLoginPageWithPreloadExtension', - PUPPETEER_EXECUTABLE_PATH: (await getAnyAvailablePuppeteerExecutable())!.executablePath - } - subProcessOfBossZhipinLoginPageWithPreloadExtension = childProcess.spawn( - process.argv[0], - process.argv.slice(1), - { - env: subProcessEnv, - stdio: [null, null, null, 'pipe', 'ipc'] - } - ) - subProcessOfBossZhipinLoginPageWithPreloadExtension!.stdio[3]!.pipe(JSONStream.parse()).on( - 'data', - (raw) => { - const data = raw - switch (data.type) { - case 'BOSS_ZHIPIN_COOKIE_COLLECTED': { - mainWindow?.webContents.send(data.type, data) - break - } - default: { - return - } - } - } - ) - - subProcessOfBossZhipinLoginPageWithPreloadExtension!.once('exit', () => { - mainWindow?.webContents.send('BOSS_ZHIPIN_LOGIN_PAGE_CLOSED') - subProcessOfBossZhipinLoginPageWithPreloadExtension = null - }) - }) - ipcMain.on('kill-bosszhipin-login-page-with-preload-extension', async () => { - try { - subProcessOfBossZhipinLoginPageWithPreloadExtension?.kill() - } catch { - // - } finally { - subProcessOfBossZhipinLoginPageWithPreloadExtension = null - } - }) - - ipcMain.handle('check-boss-zhipin-cookie-file', () => { - const cookies = readStorageFile('boss-cookies.json') - return checkCookieListFormat(cookies) - }) - mainWindow!.once('closed', () => { mainWindow = null }) diff --git a/packages/ui/src/renderer/src/main.ts b/packages/ui/src/renderer/src/main.ts index 6ded8fe..dfde866 100644 --- a/packages/ui/src/renderer/src/main.ts +++ b/packages/ui/src/renderer/src/main.ts @@ -6,5 +6,6 @@ import 'normalize.css' import './style/public.scss' import 'element-plus/dist/index.css' import 'virtual:uno.css' +import 'animate.css' createApp(App).use(router).use(ElementPlus).mount('#app') diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue index 02bc028..90138c0 100644 --- a/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue +++ b/packages/ui/src/renderer/src/page/BootstrapSplash/index.vue @@ -1,10 +1,24 @@ diff --git a/packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue b/packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue index b5b4701..fa38189 100644 --- a/packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue +++ b/packages/ui/src/renderer/src/page/BootstrapSplash/page/DownloadingDependencies.vue @@ -1,10 +1,11 @@ diff --git a/packages/ui/src/renderer/src/page/GeekAutoStartChatWithBoss/RunningStatus.vue b/packages/ui/src/renderer/src/page/GeekAutoStartChatWithBoss/RunningStatus.vue index 039ab8c..43129a6 100644 --- a/packages/ui/src/renderer/src/page/GeekAutoStartChatWithBoss/RunningStatus.vue +++ b/packages/ui/src/renderer/src/page/GeekAutoStartChatWithBoss/RunningStatus.vue @@ -50,11 +50,7 @@ onMounted(async () => { ElMessage.error({ message: `核心组件损坏,正在尝试修复` }) - const checkDependenciesResult = await electron.ipcRenderer.invoke('check-dependencies') - if (Object.values(checkDependenciesResult).includes(false)) { - router.replace('/') - // TODO: should continue interrupted task - } + router.replace('/') } console.error(err) } diff --git a/packages/ui/src/renderer/src/router/index.ts b/packages/ui/src/renderer/src/router/index.ts index 9f59f86..79bf65d 100644 --- a/packages/ui/src/renderer/src/router/index.ts +++ b/packages/ui/src/renderer/src/router/index.ts @@ -54,7 +54,7 @@ const routes: Array = [ path: '/downloadingDependencies', component: () => import('@renderer/page/BootstrapSplash/page/DownloadingDependencies.vue'), meta: { - title: '正在下载浏览器' + title: '正在下载核心组件' }, } ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32da681..33fa664 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + importers: .: @@ -19,6 +23,9 @@ importers: puppeteer-extra-plugin-stealth: specifier: 2.11.2 version: 2.11.2(puppeteer-extra@3.3.6) + rimraf: + specifier: ^3.0.2 + version: 3.0.2 tapable: specifier: ^2.2.1 version: 2.2.1 @@ -54,10 +61,34 @@ importers: '@geekgeekrun/geek-auto-start-chat-with-boss': specifier: workspace:* version: link:../geek-auto-start-chat-with-boss + '@geekgeekrun/sqlite-plugin': + specifier: workspace:* + version: link:../sqlite-plugin '@geekgeekrun/utils': specifier: workspace:* version: link:../utils + packages/sqlite-plugin: + dependencies: + cli-highlight: + specifier: ^2.1.11 + version: 2.1.11 + reflect-metadata: + specifier: ^0.2.1 + version: 0.2.1 + sqlite3: + specifier: 5.1.6 + version: 5.1.6 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@18.19.15)(typescript@5.3.3) + typeorm: + specifier: 0.3.11 + version: 0.3.11(sqlite3@5.1.6)(ts-node@10.9.2) + typescript: + specifier: ^5.3.3 + version: 5.3.3 + packages/ui: dependencies: '@electron-toolkit/preload': @@ -75,6 +106,9 @@ importers: '@geekgeekrun/launch-bosszhipin-login-page-with-preload-extension': specifier: workspace:* version: link:../launch-bosszhipin-login-page-with-preload-extension + '@geekgeekrun/sqlite-plugin': + specifier: workspace:* + version: link:../sqlite-plugin '@geekgeekrun/utils': specifier: workspace:* version: link:../utils @@ -84,6 +118,9 @@ importers: JSONStream: specifier: ^1.3.5 version: 1.3.5 + animate.css: + specifier: ^4.1.1 + version: 4.1.1 electron-updater: specifier: ^6.1.7 version: 6.1.7 @@ -493,6 +530,13 @@ packages: '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.9) dev: true + /@babel/runtime@7.24.1: + resolution: {integrity: sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: false + /@babel/template@7.23.9: resolution: {integrity: sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==} engines: {node: '>=6.9.0'} @@ -528,6 +572,13 @@ packages: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: false + /@ctrl/tinycolor@3.6.1: resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} @@ -926,6 +977,11 @@ packages: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false + /@gar/promisify@1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: false + optional: true + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -988,7 +1044,6 @@ packages: /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} - dev: true /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} @@ -1005,6 +1060,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + /@malept/cross-spawn-promise@1.1.1: resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} engines: {node: '>= 10'} @@ -1024,6 +1086,24 @@ packages: - supports-color dev: true + /@mapbox/node-pre-gyp@1.0.11: + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + dependencies: + detect-libc: 2.0.2 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.6.7 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.6.0 + tar: 6.2.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1045,6 +1125,24 @@ packages: fastq: 1.17.1 dev: true + /@npmcli/fs@1.1.1: + resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.6.0 + dev: false + optional: true + + /@npmcli/move-file@1.1.2: + resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} + engines: {node: '>=10'} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: false + optional: true + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1246,6 +1344,10 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} + /@sqltools/formatter@1.2.5: + resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} + dev: false + /@sxzz/popperjs-es@2.11.7: resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} dev: false @@ -1256,6 +1358,12 @@ packages: dependencies: defer-to-connect: 2.0.1 + /@tootallnate/once@1.1.2: + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + dev: false + optional: true + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} @@ -1265,6 +1373,22 @@ packages: resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} dev: false + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: false + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: false + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: false + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: false + /@types/cacheable-request@6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: @@ -1921,6 +2045,10 @@ packages: through: 2.3.8 dev: false + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: false + /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1929,11 +2057,15 @@ packages: acorn: 8.11.3 dev: true + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: false + /acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true - dev: true /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} @@ -1952,6 +2084,23 @@ packages: - supports-color dev: false + /agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + dependencies: + humanize-ms: 1.2.1 + dev: false + optional: true + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: false + optional: true + /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -1969,6 +2118,10 @@ packages: uri-js: 4.4.1 dev: true + /animate.css@4.1.1: + resolution: {integrity: sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==} + dev: false + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1995,6 +2148,10 @@ packages: engines: {node: '>=12'} dev: true + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -2043,6 +2200,36 @@ packages: - supports-color dev: true + /app-root-path@3.1.0: + resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} + engines: {node: '>= 6.0.0'} + dev: false + + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: false + + /are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + + /are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + optional: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: false + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -2194,6 +2381,13 @@ packages: base64-js: 1.5.1 ieee754: 1.2.1 + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + /builder-util-runtime@9.2.3: resolution: {integrity: sha512-FGhkqXdFFZ5dNC4C+yuQB9ak311rpGAw+/ASz8ZdxwODCv1GGMWgLDeofRkdi0F3VCHQEWy/aXcJQozx2nOPiw==} engines: {node: '>=12.0.0'} @@ -2231,6 +2425,33 @@ packages: engines: {node: '>=8'} dev: true + /cacache@15.3.0: + resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} + engines: {node: '>= 10'} + dependencies: + '@npmcli/fs': 1.1.1 + '@npmcli/move-file': 1.1.2 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 7.2.3 + infer-owner: 1.0.4 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 8.0.1 + tar: 6.2.0 + unique-filename: 1.1.1 + transitivePeerDependencies: + - bluebird + dev: false + optional: true + /cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} @@ -2269,7 +2490,6 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} @@ -2293,7 +2513,6 @@ packages: /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - dev: true /chromium-bidi@0.4.7(devtools-protocol@0.0.1120988): resolution: {integrity: sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==} @@ -2313,6 +2532,25 @@ packages: engines: {node: '>=8'} dev: true + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: false + optional: true + + /cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + dev: false + /cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -2323,6 +2561,14 @@ packages: dev: true optional: true + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -2364,6 +2610,11 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: false + /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} dev: true @@ -2404,6 +2655,10 @@ packages: engines: {node: ^14.18.0 || >=16.10.0} dev: true + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: false + /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true @@ -2432,6 +2687,10 @@ packages: dev: true optional: true + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: false + /cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} @@ -2484,6 +2743,13 @@ packages: engines: {node: '>= 14'} dev: false + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.24.1 + dev: false + /dayjs@1.11.10: resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: false @@ -2559,10 +2825,19 @@ packages: engines: {node: '>=0.4.0'} dev: true + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: false + /destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} dev: true + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: false + /detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} optional: true @@ -2571,6 +2846,11 @@ packages: resolution: {integrity: sha512-39fCpE3Z78IaIPChJsP6Lhmkbf4dWXOmzLk/KFTdRkNk/0JymRIfUynDVRndV9HoDz8PyalK1UH21ST/ivwW5Q==} dev: false + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: false + /dir-compare@3.3.0: resolution: {integrity: sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==} dependencies: @@ -2629,6 +2909,11 @@ packages: resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} dev: true + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + /dotenv@9.0.2: resolution: {integrity: sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==} engines: {node: '>=10'} @@ -2769,6 +3054,14 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: true + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true + dependencies: + iconv-lite: 0.6.3 + dev: false + optional: true + /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} dependencies: @@ -2784,7 +3077,6 @@ packages: /err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: true /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -3230,7 +3522,6 @@ packages: engines: {node: '>= 8'} dependencies: minipass: 3.3.6 - dev: true /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3246,6 +3537,36 @@ packages: /function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + /gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + + /gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + optional: true + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3412,7 +3733,6 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors@1.0.1: resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} @@ -3430,6 +3750,10 @@ packages: engines: {node: '>= 0.4'} optional: true + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: false + /hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} engines: {node: '>= 0.4'} @@ -3441,6 +3765,10 @@ packages: hasBin: true dev: true + /highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: false + /hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -3451,6 +3779,18 @@ packages: /http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + /http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + /http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} @@ -3503,6 +3843,13 @@ packages: engines: {node: '>=10.17.0'} dev: true + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.2 + dev: false + optional: true + /iconv-corefoundation@1.1.7: resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} engines: {node: ^8.11.2 || >=10} @@ -3519,7 +3866,6 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 - dev: true /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3544,7 +3890,17 @@ packages: /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: false + optional: true + + /infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: false + optional: true /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} @@ -3612,6 +3968,11 @@ packages: is-extglob: 2.1.1 dev: true + /is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + dev: false + optional: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -3646,7 +4007,6 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true /isobject@3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} @@ -3869,6 +4229,43 @@ packages: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: false + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: false + + /make-fetch-happen@9.1.0: + resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} + engines: {node: '>= 10'} + dependencies: + agentkeepalive: 4.5.0 + cacache: 15.3.0 + http-cache-semantics: 4.1.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 6.0.0 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 1.4.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 6.2.1 + ssri: 8.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + dev: false + optional: true + /matcher@3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -3964,17 +4361,59 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + optional: true + + /minipass-fetch@1.4.1: + resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: false + optional: true + + /minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + optional: true + + /minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: false + optional: true + + /minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: false + optional: true + /minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} dependencies: yallist: 4.0.0 - dev: true /minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - dev: true /minipass@7.0.4: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} @@ -3987,7 +4426,6 @@ packages: dependencies: minipass: 3.3.6 yallist: 4.0.0 - dev: true /mitt@3.0.0: resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==} @@ -4009,7 +4447,6 @@ packages: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true - dev: true /mlly@1.5.0: resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} @@ -4032,6 +4469,14 @@ packages: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} dev: true + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4041,6 +4486,12 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + optional: true + /netmask@2.0.2: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} @@ -4052,6 +4503,10 @@ packages: dev: true optional: true + /node-addon-api@4.3.0: + resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} + dev: false + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -4082,10 +4537,40 @@ packages: formdata-polyfill: 4.0.10 dev: false + /node-gyp@8.4.1: + resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} + engines: {node: '>= 10.12.0'} + hasBin: true + requiresBuild: true + dependencies: + env-paths: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + make-fetch-happen: 9.1.0 + nopt: 5.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.6.0 + tar: 6.2.0 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + dev: false + optional: true + /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} dev: true + /nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -4110,12 +4595,37 @@ packages: path-key: 3.1.1 dev: true + /npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false + + /npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + dev: false + optional: true + /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: boolbase: 1.0.0 dev: true + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -4171,6 +4681,14 @@ packages: p-limit: 3.1.0 dev: true + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: false + optional: true + /pac-proxy-agent@7.0.1: resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} engines: {node: '>= 14'} @@ -4212,6 +4730,20 @@ packages: lines-and-columns: 1.2.4 dev: false + /parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: false + + /parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + dev: false + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: false + /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true @@ -4320,13 +4852,22 @@ packages: resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} engines: {node: '>=0.4.0'} + /promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dev: false + optional: true + /promise-retry@2.0.1: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} dependencies: err-code: 2.0.3 retry: 0.12.0 - dev: true /proxy-agent@6.3.1: resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} @@ -4550,6 +5091,18 @@ packages: picomatch: 2.3.1 dev: true + /reflect-metadata@0.1.14: + resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} + dev: false + + /reflect-metadata@0.2.1: + resolution: {integrity: sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==} + dev: false + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: false + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -4578,7 +5131,6 @@ packages: /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - dev: true /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} @@ -4638,7 +5190,6 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true /sanitize-filename@1.6.3: resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} @@ -4685,6 +5236,18 @@ packages: type-fest: 0.13.1 optional: true + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: false + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + /shallow-clone@0.1.2: resolution: {integrity: sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==} engines: {node: '>=0.10.0'} @@ -4709,7 +5272,6 @@ packages: /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -4752,6 +5314,18 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + /socks-proxy-agent@6.2.1: + resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + /socks-proxy-agent@8.0.2: resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} engines: {node: '>= 14'} @@ -4791,6 +5365,32 @@ packages: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} optional: true + /sqlite3@5.1.6: + resolution: {integrity: sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==} + requiresBuild: true + peerDependenciesMeta: + node-gyp: + optional: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + node-addon-api: 4.3.0 + tar: 6.2.0 + optionalDependencies: + node-gyp: 8.4.1 + transitivePeerDependencies: + - bluebird + - encoding + - supports-color + dev: false + + /ssri@8.0.1: + resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: false + optional: true + /stat-mode@1.0.0: resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} engines: {node: '>= 6'} @@ -4874,7 +5474,6 @@ packages: engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - dev: true /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -4940,7 +5539,6 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 - dev: true /temp-file@3.4.0: resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} @@ -4953,6 +5551,19 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: false @@ -5009,6 +5620,37 @@ packages: typescript: 5.3.3 dev: true + /ts-node@10.9.2(@types/node@18.19.15)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 18.19.15 + acorn: 8.11.3 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: false + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -5029,6 +5671,87 @@ packages: engines: {node: '>=10'} dev: true + /typeorm@0.3.11(sqlite3@5.1.6)(ts-node@10.9.2): + resolution: {integrity: sha512-pzdOyWbVuz/z8Ww6gqvBW4nylsM0KLdUCDExr2gR20/x1khGSVxQkjNV/3YqliG90jrWzrknYbYscpk8yxFJVg==} + engines: {node: '>= 12.9.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^3.6.0 + mssql: ^7.3.0 + mysql2: ^2.2.5 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + date-fns: 2.30.0 + debug: 4.3.4 + dotenv: 16.4.5 + glob: 7.2.3 + js-yaml: 4.1.0 + mkdirp: 1.0.4 + reflect-metadata: 0.1.14 + sha.js: 2.4.11 + sqlite3: 5.1.6 + ts-node: 10.9.2(@types/node@18.19.15)(typescript@5.3.3) + tslib: 2.6.2 + uuid: 8.3.2 + xml2js: 0.4.23 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + /typescript@5.3.3: resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} @@ -5077,6 +5800,20 @@ packages: - rollup dev: true + /unique-filename@1.1.1: + resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} + dependencies: + unique-slug: 2.0.2 + dev: false + optional: true + + /unique-slug@2.0.2: + resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} + dependencies: + imurmurhash: 0.1.4 + dev: false + optional: true + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -5210,6 +5947,15 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: false + /verror@1.10.1: resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} engines: {node: '>=0.6.0'} @@ -5365,7 +6111,12 @@ packages: hasBin: true dependencies: isexe: 2.0.0 - dev: true + + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: false /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -5405,6 +6156,19 @@ packages: engines: {node: '>=12'} dev: true + /xml2js@0.4.23: + resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.3.0 + xmlbuilder: 11.0.1 + dev: false + + /xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + dev: false + /xmlbuilder@15.1.1: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} @@ -5422,10 +6186,28 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: false + /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: false + /yargs@17.7.1: resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} engines: {node: '>=12'} @@ -5457,11 +6239,12 @@ packages: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false