From 66fdc50c31ab62b13a66e48618541adf2eeb453c Mon Sep 17 00:00:00 2001 From: Ismael Date: Mon, 7 Apr 2025 11:32:08 -0300 Subject: [PATCH] Commit inicial --- .mocharc.json | 6 + .npmrc | 1 + .vscode-test.mjs | 5 + .vscode/extensions.json | 5 + .vscode/launch.json | 24 ++ .vscode/settings.json | 13 ++ .vscode/tasks.json | 64 ++++++ .vscodeignore | 14 ++ CHANGELOG.md | 9 + README.md | 0 esbuild.js | 57 +++++ eslint.config.mjs | 28 +++ package.json | 125 ++++++++++ resources/icone_R3.jpg | Bin 0 -> 14421 bytes src/extension.ts | 75 ++++++ src/models/moduloModel.ts | 21 ++ src/models/rotaModel.ts | 47 ++++ src/providers/modulosProvider.ts | 94 ++++++++ src/providers/rotasProvider.ts | 213 ++++++++++++++++++ src/system/directories/moduloPath.ts | 41 ++++ src/test/extension.test.ts | 39 ++++ src/test/providers/modulosProvider.test.ts | 0 .../outputChannels/r3utils.outputchannel.ts | 7 + .../infra/data/routes/teste.routes.ts | 5 + .../infra/data/routes/teste2.routes.ts | 0 .../data/routes/convocacaoAtiva.routes.ts | 3 + .../infra/data/routes/moduControle.routes.ts | 3 + tsconfig.json | 24 ++ vsc-extension-quickstart.md | 48 ++++ 29 files changed, 971 insertions(+) create mode 100644 .mocharc.json create mode 100644 .npmrc create mode 100644 .vscode-test.mjs create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 .vscodeignore create mode 100644 CHANGELOG.md create mode 100644 README.md create mode 100644 esbuild.js create mode 100644 eslint.config.mjs create mode 100644 package.json create mode 100644 resources/icone_R3.jpg create mode 100644 src/extension.ts create mode 100644 src/models/moduloModel.ts create mode 100644 src/models/rotaModel.ts create mode 100644 src/providers/modulosProvider.ts create mode 100644 src/providers/rotasProvider.ts create mode 100644 src/system/directories/moduloPath.ts create mode 100644 src/test/extension.test.ts create mode 100644 src/test/providers/modulosProvider.test.ts create mode 100644 src/vscode/outputChannels/r3utils.outputchannel.ts create mode 100644 testDirectory/modules/conferenciaColetor/infra/data/routes/teste.routes.ts create mode 100644 testDirectory/modules/conferenciaColetor/infra/data/routes/teste2.routes.ts create mode 100644 testDirectory/modules/convocacaoAtiva/infra/data/routes/convocacaoAtiva.routes.ts create mode 100644 testDirectory/modules/moduControle/infra/data/routes/moduControle.routes.ts create mode 100644 tsconfig.json create mode 100644 vsc-extension-quickstart.md diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 0000000..e87886f --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,6 @@ +{ + "spec": [ + "test/*.ts" + ], + "recursive": true +} \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..37d1b60 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +enable-pre-post-scripts = true \ No newline at end of file diff --git a/.vscode-test.mjs b/.vscode-test.mjs new file mode 100644 index 0000000..b62ba25 --- /dev/null +++ b/.vscode-test.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from '@vscode/test-cli'; + +export default defineConfig({ + files: 'out/test/**/*.test.js', +}); diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d7a3ca1 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": ["dbaeumer.vscode-eslint", "connor4312.esbuild-problem-matchers", "ms-vscode.extension-test-runner"] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f9c36b3 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "cwd": "${workspaceFolder}/testDirectory", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + // "${workspaceFolder}/testDirectory", + "--disable-extensions" + ], + "outFiles": [ + "${workspaceFolder}/dist/**/*.js" + ], + "preLaunchTask": "${defaultBuildTask}" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5c5ac48 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.exclude": { + "out": false, // set this to true to hide the "out" folder with the compiled JS files + "dist": false // set this to true to hide the "dist" folder with the compiled JS files + }, + "search.exclude": { + "out": true, // set this to false to include "out" folder in search results + "dist": true // set this to false to include "dist" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..3cf99c3 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,64 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "label": "watch", + "dependsOn": [ + "npm: watch:tsc", + "npm: watch:esbuild" + ], + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "npm", + "script": "watch:esbuild", + "group": "build", + "problemMatcher": "$esbuild-watch", + "isBackground": true, + "label": "npm: watch:esbuild", + "presentation": { + "group": "watch", + "reveal": "never" + } + }, + { + "type": "npm", + "script": "watch:tsc", + "group": "build", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "label": "npm: watch:tsc", + "presentation": { + "group": "watch", + "reveal": "never" + } + }, + { + "type": "npm", + "script": "watch-tests", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never", + "group": "watchers" + }, + "group": "build" + }, + { + "label": "tasks: watch-tests", + "dependsOn": [ + "npm: watch", + "npm: watch-tests" + ], + "problemMatcher": [] + } + ] +} diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 0000000..159277f --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,14 @@ +.vscode/** +.vscode-test/** +out/** +node_modules/** +src/** +.gitignore +.yarnrc +esbuild.js +vsc-extension-quickstart.md +**/tsconfig.json +**/eslint.config.mjs +**/*.map +**/*.ts +**/.vscode-test.* diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ba2b707 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to the "r3utils" extension will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + +## [Unreleased] + +- Initial release \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 0000000..2616396 --- /dev/null +++ b/esbuild.js @@ -0,0 +1,57 @@ +const esbuild = require("esbuild"); + +const production = process.argv.includes('--production'); +const watch = process.argv.includes('--watch'); + +/** + * @type {import('esbuild').Plugin} + */ +const esbuildProblemMatcherPlugin = { + name: 'esbuild-problem-matcher', + + setup(build) { + build.onStart(() => { + console.log('[watch] build started'); + }); + build.onEnd((result) => { + result.errors.forEach(({ text, location }) => { + console.error(`✘ [ERROR] ${text}`); + console.error(` ${location.file}:${location.line}:${location.column}:`); + }); + console.log('[watch] build finished'); + }); + }, +}; + +async function main() { + const ctx = await esbuild.context({ + entryPoints: [ + 'src/extension.ts' + ], + bundle: true, + format: 'cjs', + minify: production, + sourcemap: !production, + sourcesContent: false, + platform: 'node', + outfile: 'dist/extension.js', + external: ['vscode'], + logLevel: 'silent', + plugins: [ + /* add to the end of plugins array */ + esbuildProblemMatcherPlugin, + ], + // ignore: ['./testDirectory/**'], + }); + if (watch) { + await ctx.watch(); + } else { + await ctx.rebuild(); + await ctx.dispose(); + } +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..d5c0b53 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,28 @@ +import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; + +export default [{ + files: ["**/*.ts"], +}, { + plugins: { + "@typescript-eslint": typescriptEslint, + }, + + languageOptions: { + parser: tsParser, + ecmaVersion: 2022, + sourceType: "module", + }, + + rules: { + "@typescript-eslint/naming-convention": ["warn", { + selector: "import", + format: ["camelCase", "PascalCase"], + }], + + curly: "warn", + eqeqeq: "warn", + "no-throw-literal": "warn", + semi: "warn", + }, +}]; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..8054772 --- /dev/null +++ b/package.json @@ -0,0 +1,125 @@ +{ + "name": "r3utils", + "displayName": "R3utils", + "description": "Utilities for R3 systems", + "version": "0.0.1", + "publisher": "R3", + "engines": { + "vscode": "^1.93.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onView:r3Utils.rotas", + "onView:r3Utils.modulos", + "onCommand:r3Utils.rotas.openFile", + "onCommand:r3Utils.modulos.openModuleFolder" + ], + "main": "./dist/extension.js", + "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "r3utils_structure", + "title": "R3utils estrutura", + "icon": "resources/icone_R3.jpg" + }, + { + "id": "r3utils_commit", + "title": "R3utils Commit Builder", + "icon": "resources/icone_R3.jpg" + } + ] + }, + "views": { + "r3utils_structure": [ + { + "id": "r3Utils.rotas", + "name": "Rotas" + }, + { + "id": "r3Utils.modulos", + "name": "Módulos" + } + ], + "r3utils_commit": [ + { + "id": "r3Utils.commit", + "name": "" + } + ] + }, + "commands": [ + { + "command": "r3utils.openFile", + "title": "Abrir arquivo de rota" + }, + { + "command": "r3utils.helloWorld", + "title": "Hello World" + }, + { + "command": "r3utils.caminhoModulos", + "title": "R3Utils: Caminho dos módulos" + }, + { + "command": "r3utils.modulos.openModuleFolder", + "title": "Abrir Pasta do Módulo" + }, + { + "command": "r3utils.helloWorld", + "title": "Hello World" + }, + { + "command": "r3utils.caminhoModulos", + "title": "R3Utils: Caminho dos módulos" + } + ], + "configuration": { + "title": "R3 Utils", + "properties": { + "r3Utils.caminhoModulos": { + "type": "string", + "description": "Caminho que se encontram os módulos" + }, + "r3Utils.caminhoModulosTeste": { + "type": "string", + "description": "Caminho teste que se encontram os módulos" + } + } + } + }, + "scripts": { + "vsix-package": "pnpm vsce package --no-dependencies", + "vscode:prepublish": "pnpm run package", + "compile": "pnpm run check-types && pnpm run lint && node esbuild.js", + "watch": "npm-run-all -p watch:*", + "watch:esbuild": "node esbuild.js --watch", + "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", + "package": "pnpm run check-types && pnpm run lint && node esbuild.js --production", + "compile-tests": "tsc -p . --outDir out", + "watch-tests": "tsc -p . -w --outDir out", + "pretest": "pnpm run compile-tests && pnpm run compile && pnpm run lint", + "check-types": "tsc --noEmit", + "lint": "eslint src", + "test": "vscode-test" + }, + "devDependencies": { + "@types/mocha": "^10.0.7", + "@types/node": "20.x", + "@types/vscode": "^1.93.0", + "@typescript-eslint/eslint-plugin": "^8.3.0", + "@typescript-eslint/parser": "^8.3.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", + "esbuild": "^0.23.1", + "eslint": "^9.9.1", + "npm-run-all": "^4.1.5", + "typescript": "^5.5.4", + "vsce": "^2.15.0" + }, + "dependencies": { + "chokidar": "^3.6.0" + } +} \ No newline at end of file diff --git a/resources/icone_R3.jpg b/resources/icone_R3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4212a82cd987b973fffdccecbcc7c19d00d50005 GIT binary patch literal 14421 zcmdsec|25a`~MNLB!fuVMj;|ZA%&r0LXu<&nUKAR?8ZzXWDOyNP$V%aYnHJ~$|PH4 z8DrmPtix=-Hbo>}T0K*!S;e-Os_!$;rXa!NJJ|;o>~NeSm}GAn!qL z2oDc04<{GjAwHf%;5pCUAWVCb%q;AnAkP7g1K`#F!-LTX@Uk=6GubmU9S8RDGBNWq zF##jpH0F_&H9Vp)^GjUJ-p8GG+g4$i}ZM~(_fosgC}DSK8$RqdSm`Ae5| z_25_Z4NPyEnOj)ivU0fV=;Z9;>h{pb*Uvv7FeohiNknAS)99q+=P9XaFVZve@?XCx zD12M=?&GKOipr|$n$OKGt!?ccUpl}3?Ct9x82mLfJVBV8nx2`Rn_nQUt#52@ZIgF) z_w-@{nEykqziak~Uc8`Q`&huQlxK znm8oR+#m|rd-rf2mOMKlMcPyCZ<_t@DHi&FrP<#V`|o-U16<5Z;E%`53&4P#=x7CF|y9vUHQt2k?58Jiv_1rfk=%SIt=d^KX0G7U6!2l-B zh!#zBE%^Y+-GCS)2JrL6;xGPjLqRWSe|%*XmUOfmzoJfpZnWdO{->ED~txN@Wm z8vg>u!2sr71=P}aE5WDVM7MlE9by1I+9dy3cLva2yj0hd0UO}zqNA{luul(iz9ht< zCw~1Uwf-+c_x~pJ9u%rtR|M@2U_v|D!4jcDQ1S^#v*#|9dVA+Ln)Gf)WtA*dpQ-&b zz=5zdFJoGHfhMC|ww$KVWCF^lY{%R%P2ici?!Sd0@_+m$nWlIgCW8#20Q4VY9MOi~ zVY(kkMz0NS=jhgq%P`YleBsm6`XVxjv#Lyf=W;%L_*zZDsOw4!+GVBCLAdPIdA7)t?@Xrz>rIoS)(yZP<4N|X9H##m=S`K%gt6%7S$2gg zs9;W=SIYn2I(52XMCM6E%UvV zq_>eLEj>`R--o*p>7^_Z3fW)pejjB-AJ18Pn0=f9V2of4K;HqwcD&1V<^{&ito;30 zWc~|6VOZ|6cty>&8dc4IsRT5A@HUyx2@K#!K3%wF%Zvf!z8EsnQ zH(c3+(36%V!hBj`FaxSSCV-ZJbq-EQK=7s-nb^V(1o-CF_P^oMd6D|f?+g4`j%z2| z6D}P#kAO0&d|1#pvZnZie<93LsL9aUBmaX zZ+Em=y9#ID-}pV$Ax3I$Zm!KK|MgPKR*4v4a;DzP0lA<_2zD+9w`l| zz7h`im~>q;*uLTS$%*%34w3N^!}b0K!?4z!C6uT20h8YA@Fk}(iY@*7*zpv*GIC9B zb2rm|a_8N;-SUM;ArOPj5Jk(MDqS+0@`5+ZvE|R5F2vkQwHygnPCAI<9@NF>MA0?K z?nMmXUciC2;q0fr&n$;+1oV}LdRNYE-GK}AN8ziz$DZ6q4(=Q=AqX-6MZ3a8N?M28 zL8LrI3*Dr<>}y!;$w~FEsOp_byZ3+`+N~_^G*3_D!KLM_V!Cj$ubdhtKh;$=R77n3 zB%H)o>n5GFe=vXiH0v$P2RbY~@ayiAN<)4U3OS!z^~RGmsj9N63L1S`-G?UOjSOHP z)ra^pTaZ-n^5~BegmC(K#I;Kp9OuAA<33CGdpA>RJ zgc1*KHaw8Lx}ljKRJ7Fus}z_)3}R z+>M_rVgm~t=R1yz@Y30Gk4Tg_4K9==Wz58Uc5XXYU904h7j4fellSP47Ir-^T1NSg zi;vEaheOxQ>%iFPa5$3zyipol;h9H7{)_z!QMcpJafUr~=l%x_fH=D#k1|4ykFPx( z+cRIy|1jSH9Yiv^YMc6UI|{pqGX}%FLq#%;v<_yg`1YS9Ly56M&Dn-uKnE7KCnI_ ze&7gfG}dBPdP$K;fJGt7RU@VPv>X#65;uQ8vXJnRx~#GBC7p0?!xT|M(c8Bru(N%{ zVdNd0O)#&Y9@%&I2-<5f?KY3R7xZX@JlPqa^GF3E7LeO@$tCYXu;V>_{|7^B6UKfL z$-nj)1B0GFET+|#CrHhcgvhqV1kQQ?Cv}?mfe5d>|5-pp9MJVO7Dr&rGv; zE5@*I$u~=(*W%}jLrr;o#D$o^eDzxrzFhA$qr~Ydy{+m7UrEqfvQ$-CV!T=W?zCbs z!TPy|-Gq@~hn8SJ5=yvW;#J_b_0h_vquuX(;GNLwAFn3$>pBScx{OD#rLo=%!tEJ>;(pZFNAX6>7^P?prg&rDd>t<$@*Bw>rAQ8 z?8DNv$`=w|8{U2?74M^jwn*M~-pS`$<$hg z5%7qB40Q?n(%5Q8iBNV;c1%wIT#R%CelfUZZ4O!LA9+(QShpOj1ZEz)`K|wKm9Jm1 zf~G2${)FE|=hz?Mo6VXSMmHD?MK9U+qBjc8)0#!)h}#ov)D#R01NhZezyRj2`clHr zTg=wEQ{8M6*0qWwv5~OrGuRVY&($6ERbKR9b`Ar0T{gI=pjEM>LP0ZtPFz4Fy>5d6 z&`!ixS6`y*LAMrZ+_BrV-kF3f(4WvW$UpL;uLXO%Ft39678hZ5ug-t+sGZd744hGf zQP#evl8HLoyO~*abJUj*lWNX9Gc14q=Dv_956#8JXet_( zneAv!6K$AWRsQmJ;+RK=C@H2rhgeD%Ab)CqH{sN?k(rr^+&B|{T#9;E7A8d1%W(CO za$S)OJdqf4q1MC6-dkU@Q@RB82{o4Sq%C0yOQ@*2Uod0HF0wuBd0ZN5<1lB0GEfxQ z961V4hTOoIFK>%Md2Y@W357f(sO@X0*sZ4k82%%V4EQp!=?4ToZq`&JrpH~>D$01|x8 zncR>ZR8Wx6>5+K3^CkZW>oZ78w)<8pRtoJIV+m$NZczSCF@Kw;!mm4;^bStad~;3#Dh&NF2KOrXgdH>6|dx>}RABi`2)xTTL6RXXT9XVSt zttKe8X!YSk?rH<3bh0%J5`0WA5&oDZl5?hY}qM!&3u&E?om?{ z3rb+uM&>)R`__xTuZxr*x0QjuO;Uj6Bne~;XCPTv(!W5P1&kMNb^C@7W#Q&c5$vP zHfp9WT6j+AI7zeO^UC#+NuT=&6B9#(d~9pi(Wunp2Hn?YKV6K@H8M@OGz%fiuu(H1 zQ4C;l68qfCxg z-1(& z8k}5AJ{GJ0hL$NIvhz{Wa&|BP8W${z1fe*qI4L{`+8BU5Bl4@7qyXlssprd2N2LFr z6Fmkc9z*0zKhL^%Uq*2T-sd1IYZ=(N1ykH}O>e0i;3@)E8urco42YTZe|+|CLO?Z% zJ7?x#4Q+Tt;)>TeCkN)YnTW;oHuX^QL~FJzc@P$_ATIBKrwFDXJmAAC%(_C^;|t%G zmu^}t2%wxn4Xlp}87^VkauCmcK4_`YdM~#ox3$ohc7yh|&TcwIX*fpMQQY^pGxriD z;uMStQR=PQe`*9!$FwTOW}h~OA}vYi*xY2KQ0XUMFOP>gBS#_6VJyQi&fYMWb^BS< za+(Q+GMQ=xwt!Je`ITUzShTL->9>+QJ9?vv7z0-O5!>F1qZp2{I} zQ+gmCXaeX03v!fOsGmm|KvF#c;yLz~0Svj%oC}jE$-H)`P_o9SZ|h@Sdp0Lu?7-|& zu?Zp$O&ma!qiF&RfCoK34d&voiT79+2Cyqf7iR$2F1o-vcEL|>XOIwtUSx$#J1>>G zd`GFETW+Cx7{G=FRfhqf)2N_LM0})yzwI1`97YFWJQ+;TO}!8}Xe;`6A1o#3V@e7aEA7MSGaVF?fl6*~dn&5Wi8fVNV9Y3CM2F5?U$4)MR5 zAV0Qm$zr{O1X+Z z>Xw4C8$s@xXJGH#edY@gHe8Lj1e{OBvW+2{7w>zjSZ^aM)z)UGc-F)=c65=DSk&I%d zO7~I~z26RxPSAf0INmrSTzH+!t>xV-CN_uA5f99ryvz)0Xni2T&7cDAH;St*ymmG( zS2S@FQ8C-b-XK6_C8?H)HYS+#Eq5mrJo@EXZgbM8Yvt(-=-uxvk_H;`XjrZDZKO+t za1;k|6Q83^v`gyi6yBF6_znJYvQMEu7X5kZLI2t&DyQXWaMPWgnfm!f5C?jAJ+;iB zmJOe01%u?3z(2tr6A1qPEd{&R@el1elYNVEpNjRHvY$&HiV6rRyQ-(J{Td}FZt?}N z&;{mEytFi!i=v1Te-N}e3w3VlUf}jt!B-LImS$(khJRY7+%YOs^;D2 z!>E!s-=r&QVpb&}9)0WyOdM>bX!B7iR-O!HKAirM~aY_i9O}N*o zJ4siK!$JdD1k@#@XV*t?f~lrvGCJorLmJ>ksdwfa?oQq?ch6lf1o;#4iCER`)9z5A zy6b5M;jk^O_@%d_TU`$tRWI;FpMS8qHU6YddIG~Tm)amqjE`}BJ@4nnCv0sQdOV)W z{d!Y!O<(fmK!w0g<%P3tPJH!&xBcd~p|>KNOh$z_L!BpFEjY zO$t}lg7jJzpRqOgG|I2(*TM@^`}EOb0RbH)yp+R}L>yy^#jH$BsK&3~JewfUW`-uA z%&@zw;p0sGDiH4Z`)?O1ex2_Zm~8QP?NY_}|9ZZ5I$u(RuYYNyJY}uFxW5%QY@YIa zCHO(1kjZrDM`na9>i2ks6t)?`)kR!wvI3z|c&|;^y`<)m`P8_VU#?I-e)yu(cNgn8 z3R^a%xCgl7X>SI@P|#5;ciXcMesq?Fr|z0e9ey4!bUjG-H&pf9!JWvGMXRc(D(>~c zwtdprKF?{_mC{1*pGFcQsrEt12(y+EO%0`k4tSACQ(oC zR9mKGw!Y^4NvkC6l`4hEFAM()OZBx6fYxPk2F%GqFaDdTyce1OYOGdETKq^;l5-PA z_!oJ-X)xPtI`{Wk1>a`)&oyHh;Q*3+o%`w48pg^kOIxdreP=ZIAsETGd=6s ztXTR&EbK|&^etoYP>2CFO{23gWuVTtU<;kQHRPvtZa4@V=wVD?0PN)84wO(IQi4#T zEPu(MU)()7GZ18!bJ^Z~ICm^k{E;5Jz|KL+RaEz92C%d}S@2Wgusaswc52;aI2qmL z@)%l+YQFr%T*UdV zhTuH~tq9f+XRJo^5)Urdz$AN;`^3W02lktOQF)5bIqHspAg$k!2V3Ge-GVL?2>k^K zL2SSygY5@geHYvq?> zuR<@F!MMqp+9aps{q+-BZe2HfOVfPR%pblltKM=vhkLth6^P+2@0OAG-=g2FupKcOOb}M@oSh#@ds9ypC&DGu}kz;`Nys zO&hFyz}#1xfim*rnh=+fh6+lk7B^KA#EI4uic~(Z`o<3l!*amp(gMI*Axq^rRX1RK zu>`iWL0`wx5NYcb44zP=@r`q!@u|N- zia(#`TgU*ka>k$w8`zgr*hoXU2f~Wh1Z6|^YJSaLLM;@aP)aQm+*pi9dc zz-%w2<)5DjB^ILi{K$WwDY`kE49@a$RWpJt1y&mgAXdH&I%{0vcH}NraTdlSH|IG7 z*?QgAurHvPBG`J!_#wXD%~vQ~r0nA}qC%c%6kP=xsJ&q3zKH#uIWgV>qG)>e`K_W? z0fH^N_ow{LWz!C4+~xU_Tk62Z^^X0^xkW@;x7x|0i*3P{S9QfCn!1KB_6&~~%?uW5 z6!X+b`JvY4gHm(eyHi9wcu`*ZnyTX?LG{s&Iy{N~6Z&a3678b6uj|z~`}@r<@m`nRbmNS%dm-)OeD+9SK{INK zlNv!P45R8289?iBLKxM$pwsT%{KF#($50(_#Wx)9=&*o{zAt9k_W5^<4eqzULer#d&n_(IpWZD!cdYzImsm zLdjkn*?@(iMH?iLT%>)A*=&Q7@f@N?Gnp3z%j>jJONq0k%FJA+JDUV{3n>@qKgBp` zxpfM@w^`%j%kIAWT#$T*S-v=jU`q8mlvT=hZtCP0OnX+vFRB#z4FMCTrQS;ooDi;z zU-(}6ompwE6ffx+p?$uXiOlo<^iAINoq9KMLUby6AXKRdj2PIxt4ELhykWYFMD8gnTh^AA%G9!@m z_uZ^tL-svMrvIW0PWx|Q1_IDZ^q!_7LqdE4mG0c?^uqWZL9{X`7fkTCA!q;5mHg-V z!M)J@<$|D$TDu~)TBc>P^~gjqgD@d>EK zqua8KC&rTT_a$yrmW2+RRaa;0`YAV;>Ky1`jlv{1-Ensk(2QgCuURH2@e@C6rHCeO znY&=RJ;_0Wt&m-*T{b$a5uBFI_eWF!*)>10$U7KR zkJ!F`4ad@epsp+KqIMf!CMy!NY)&a%v0RygjuGl>1ttb_O%L9<>4r3X*z?9*<<+}O zPRL0xs_kO{$@U}&4F$THT{BUXvBe^U%71`v6w?aZ+yR~4{7v5-O+-EsO^E>+E-hnC z1`xQzfyjk^h+KB_wY=BBMm6j|6T%sV)OqVKUq+f zq98vVQ1CRYo+Ret+D!Baif_1l&5XsDz_TzZZ`IKyPYiF-QbDiJFSH$ z0rsx%o(<&)(MJ#;wMqS1gYA&W^BzdJBR9?3_=$R-oesSMIO^KxM_0Md_6_j-jEIj~4y+M4<~7J|1&`7%$ddw#w){$b+f zcIvNFhP_MJUTOlHT9-O@_~c$OE}cl@4>m!dDzxrUz*vw;vUk@EzD-sy8ijsx;}vx< zG}n;qnQ+$KzAG~}W*Rg&cN?Wh?;1Oi*$gXJe54Xp;L_s$!17BYQKH84Q$tAQ*CEUh zbq1?IsFQp^UUd~Mz^pHXq{46aw|I92%-tL~TP*rezrM#;=5Vml#W6$csLa=ipHm#Q zTKVLNUF}-JHAMfI3M|K%2SqRL?Z_{~>{b5QaJoC9R)D-iadjzrMeog4uZY%6#QCx= zP^-C|E2AwW250@KI;GuQrIS%b@O%pjcA^_4UXXRJZwYs3kC!r?-ZQhm(C%OF|DKn^ z;#a9DI2QD;j=dVhOtjKHG>z}bWwV2&QI)+y1RAVE#L(-{f^`U~cW1q*;P%G`f8!E~U3k?V^3q8Cq&zsQP^Q+vQ#o zrX+9+^K_5!+}-dOV;FOXL{g-;unXuf!ymA~x8m7|lyMvzo@IjI3esjApIRl-r7HI;*!<35#Y;`@5a=*POvBDr3Racgf_QS(aF ze`FS#SY4q6TvKuQF6e{%y88Rl*7Zz$Y2Da4;_a6he7(K5pNu>$<$}o0DKGkakQP^! zhBXHQRo_lv{WXjxve??KSQ)?*s?nR4x2{1i4|@9ESDwDBN7E725ea2FavTd*pxumz zu-3F}m`A77GGt!?(7d~H_1P#^*#i36*c}FHc?20 zS3HI}_HIA?K}&_rN7I~C$kP-%_e65!)(g^B?xEsSR!P5-l(tK9<3~2OqXslY*-rVq z8CG1^8(J!fm|nq&<|UP0%f+dF);c7{|C#DRHpB754i;{|grOBh~(A#)zGot=qH3j6ZDA{4ZNPF>D1^ z3;(v=D8vGU;j^R-lpuLtEqqm)!;>(oYG~PXkJ*=F-2q2saxz(InM0e%5p$ZeW%`ka z2yxQwLLw2GmvrkQc1LSHD0t~uzSf-kmS?gpGsO<|odo7p+{@hTrftLQ?r|ra z8rPekn#D?Zw#Fuy?<0+UL+b(lXK#7PjiaW@(fQ}s??DIVD7E=(TG2Vzdp8fBpwAli zpPDJJD^GcqJ$6@4^2W&)xsy|;#X~jUHMnm^HMp$HCp>lQZtl_LZw>NXqL9Yhpn!%i zB)a_6$S+)!?|qdVj$lt*7rm?0P{L2s`vCJUjkro+dqS59fE$yl!YZWde{RaOCRUN! z$J<0=s0xLl^--9XGqx0p6utLzVI%bL0a0`P6)Lp&TmH>*ma;03&;=+Hu^ z%p^Xa`)+VvA8OO*riZ(UO9XeC7!Sc(5&P=yPr~@fT}$iVj=1ceBJo__y89mE74NsA zWrbhkyrOTNb*aH8P>yVj(`4hZo@p!5ARq=e zQ2etUj)MDCgwR51`BdDy2?j8M>ocbm{6o#Y;6H2jav{A4aa0fVLn?;UMJUK83E>DT z1&N|mRZ>W*kxIc`rOQQG&AMzC9{#LD3Agt&PHL9;J33({YE^Shc_XI^N>>uTEm%=9 z>7wog=iG@Sz+I^hPor385i++r6EW|Ay8FpL$iq6e;iqN7l3-!uvZsgW&b^BQJA zTEL1NNsl=U%7i+DTWkCFb5iRB|pt`wQwmd{^TzR?=R4@S5V%a-G z*&0k;ls&Y-%p7`w_scQ@{+y&Bpaf$ z0JtxWPhWoaiSNOO%~gDSU83d9Grzg0#Drg~f7|kP%spP=1=Qp)i*|hL33!Qf6k&u_ zfKuDJi%x$d62ogU=68hz?tePC-A)Nn*w!7WyWouy`4acA5MeuW=wQ>mluE8Mr#!r^ zp|T&O)g{$Np0{3)7Pu*k(TNYuL1a0QVnm}-d)~ty!Jk9K z!^S5yjraMj>Tf1OZ$^^KO?#>Bc%+Iilx;(T0uO0@gE(=U+4cGP1pX3rcw2* zC^6)T>Z(uVBK+^#n#oXhq)wr}WYX!Imj#uQz8M36vOZ?$GP#NP{Bc6G7B6gDc#l_F z#Gm{6a@IUewgKDfAs>@h1NpNTO03obr`~fNr1Q8-u;kC0PY~1S2fb#9=}+bi=@%~!JOEybo|z{mH76gy5HAnZ_v)8s*2|)C*fhDA@ZBW zfxqcHaZhP--!vS-M4XfMlBy(Jn)u$WLAu(c)yg(|p|+M;sw1^}Q`VZKVZQN^YUbZ{ zEfamhS;I`oZ7qp{E0BvIV@SmlxTf0&D{#<&=mX+kjp{Rawk__#B4j?LsyE^|m6dgo zhe(&`oJOPztv$Fxq$-h?7QSqA-@5aKt*t|Wg?CghR#;dx4w*}U@C8J+4VMpZNBb5p zTimF=_uV(}f}tGk*3)xabEoCzz3Ds{lOhMG>{69Rta-3OMumVsS!|qQh#I7yBh$Qx zOzsMP7;~9PjW)j>>7|~ZVI}i%N$^mH z`kTBMg{J@61uZx5)&n2%qEANsGk*SOihA#VWB$i@`X90N|HHXXq3oWXr}Ls^fd7J~ UvNyQ+f5E_ell`w99L5;>Zy*&VUH||9 literal 0 HcmV?d00001 diff --git a/src/extension.ts b/src/extension.ts new file mode 100644 index 0000000..712d7e6 --- /dev/null +++ b/src/extension.ts @@ -0,0 +1,75 @@ +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +import path from 'path'; +import * as vscode from 'vscode'; +import { ModulosProvider } from './providers/modulosProvider'; +import { RotasProvider } from './providers/rotasProvider'; +import { ModuloPath } from './system/directories/moduloPath'; +import { getR3UtilsOutputChannel } from './vscode/outputChannels/r3utils.outputchannel'; + +// This method is called when your extension is activated +// Your extension is activated the very first time the command is executed +export function activate(context: vscode.ExtensionContext) { + + // registrar providers + let rotasProvider = new RotasProvider(); + vscode.window.registerTreeDataProvider('r3Utils.rotas', rotasProvider); + + context.subscriptions.push(rotasProvider); + + const openFileCommand = vscode.commands.registerCommand('r3utils.rotas.openFile', (filePath: string, range: vscode.Range) => { + vscode.workspace.openTextDocument(filePath).then(doc => { + vscode.window.showTextDocument(doc).then(editor => { + const selection = new vscode.Selection(range.start, range.end); + editor.selection = selection; + editor.revealRange(range, vscode.TextEditorRevealType.InCenter); + }); + }); + }); + + context.subscriptions.push(openFileCommand); + + // rotasProvider = undefined as unknown as RotasProvider; + + + const moduloPathExists = vscode.workspace.getConfiguration("r3Utils").has("caminhoModulos"); + if (moduloPathExists) { + + const moduloPath = new ModuloPath(vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos")!); + const modulosProvider = new ModulosProvider(moduloPath); + vscode.window.registerTreeDataProvider('r3Utils.modulos', modulosProvider); + // Registrar o comando para abrir Pasta do Módulo + const openModuleFolderCommand = vscode.commands.registerCommand('r3utils.modulos.openModuleFolder', async (modulePath: string) => { + const uri = vscode.Uri.file(modulePath); + console.log("Abrindo pasta do módulo:", uri); + await vscode.commands.executeCommand('revealInExplorer', uri); + await vscode.commands.executeCommand('workbench.view.explorer'); + }); + + // const openModuleFolderCommand = vscode.commands.registerCommand('r3utils.modulos.openModuleFolder', (modulePath: string) => { + // vscode.commands.executeCommand('revealInExplorer', vscode.Uri.file(modulePath)); + // }); + context.subscriptions.push(openModuleFolderCommand); + } + + // Mostra o caminho dos módulos + const caminhoModulo = vscode.commands.registerCommand('r3utils.caminhoModulos', () => { + const conf = vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos"); + + const workspaceFolder = vscode.workspace.workspaceFolders?.[0].uri.fsPath; + if (workspaceFolder) { + vscode.window.showInformationMessage(`Caminho dos módulos: ${path.join(workspaceFolder, conf as string)}`); + } else { + vscode.window.showInformationMessage(`Nenhuma pasta de trabalho aberta`); + } + }); + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + // vscode.window.('Congratulations, your extension "r3utils" is now active!'); + getR3UtilsOutputChannel().appendLine("Extension r3Utils ativada!"); + + context.subscriptions.push(caminhoModulo); +} + +// This method is called when your extension is deactivated +export function deactivate() { } diff --git a/src/models/moduloModel.ts b/src/models/moduloModel.ts new file mode 100644 index 0000000..f753b14 --- /dev/null +++ b/src/models/moduloModel.ts @@ -0,0 +1,21 @@ +import * as vscode from 'vscode'; +export class ModuloItem extends vscode.TreeItem { + constructor( + public readonly label: string, + public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly modulePath: string + ) { + super(label, collapsibleState); + + this.command = { + command: 'r3utils.modulos.openModuleFolder', + title: 'Abrir Pasta do Módulo', + arguments: [modulePath] + }; + } + +} + +export interface ModuloModel { + getDirectories(): Promise +} \ No newline at end of file diff --git a/src/models/rotaModel.ts b/src/models/rotaModel.ts new file mode 100644 index 0000000..48c31c6 --- /dev/null +++ b/src/models/rotaModel.ts @@ -0,0 +1,47 @@ +import * as vscode from 'vscode'; +export class RotaItem extends vscode.TreeItem { + constructor( + public readonly rotaInfo: RotaInfo, + public readonly collapsibleState: vscode.TreeItemCollapsibleState, + public readonly children?: RotaItem[], + public readonly command?: vscode.Command + ) { + super('', collapsibleState); + + if (children) { + this.label = rotaInfo.modulo; // Nome do módulo + // this.command = { + // command: 'rotas.openModuleFolder', + // title: 'Abrir Pasta do Módulo', + // arguments: [rotaInfo.modulePath] + // }; + } else { + this.label = `${rotaInfo.line} - ${rotaInfo.metodo} : ${rotaInfo.nome}`; // Método e nome da rota + + } + + // if (rotaInfo.metodo) { + // this.label = `${rotaInfo.metodo} ${rotaInfo.nome}`; + // } else { + // this.label = rotaInfo.modulo; + // } + + this.tooltip = `Rota: ${rotaInfo.nome}\nMétodo: ${rotaInfo.metodo}\nMódulo: ${rotaInfo.modulo}`; + } +} + +export class RotaInfo { + constructor( + public readonly nome: string, + public readonly modulo: string, + public readonly line: number, + public readonly metodo?: string, + public readonly filePath?: string, + public readonly range?: vscode.Range, + public readonly modulePath?: string + ) { } + + toString(): string { + return `${this.line} - ${this.metodo ? this.metodo : ''} : ${this.nome} (${this.modulo})`; + } +} diff --git a/src/providers/modulosProvider.ts b/src/providers/modulosProvider.ts new file mode 100644 index 0000000..6e21f36 --- /dev/null +++ b/src/providers/modulosProvider.ts @@ -0,0 +1,94 @@ +import chokidar from "chokidar"; +import path from "path"; +import * as vscode from "vscode"; +import { ModuloItem } from "../models/moduloModel"; +import { ModuloPath } from "../system/directories/moduloPath"; +export class ModulosProvider implements vscode.TreeDataProvider { + + constructor(private moduloPath: ModuloPath) { + this.moduloPath.watchDirectories(() => { + this.refresh(); + }); + } + + private watcher = chokidar.watch(vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos") as string, { depth: 99 }); + + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event | undefined = + this._onDidChangeTreeData.event; + getTreeItem(element: ModuloItem): vscode.TreeItem | Thenable { + return element; + } + + refresh(): void { + this._onDidChangeTreeData.fire(); + } + + async getChildren(element?: ModuloItem | undefined): Promise { + // if (element) { + // return Promise.resolve([]); + // } else { + // let directories: string[] = []; + // await new ModuloPath( + // path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, + // vscode.workspace.getConfiguration("r3Utils").get("caminhoModulosTeste") as string + // ) + // ).getDirectories().then(dirs => { + // directories = dirs; + // }); + + // const modulosItems: ModuloItem[] = []; + // const modulosPath = path.join( + // vscode.workspace.workspaceFolders![0].uri.fsPath, + // vscode.workspace.getConfiguration("r3Utils").get("caminhoModulosTeste") as string + // ); + + // directories.forEach(directory => { + // const modulePath = path.join(modulosPath, directory); + // modulosItems.push(new ModuloItem(directory, vscode.TreeItemCollapsibleState.None, modulePath)); + // }); + + // return Promise.resolve(modulosItems); + // } + + if (element) { + return []; + } else { + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders) { + return []; + } + + const configPath = vscode.workspace.getConfiguration("r3Utils").get("caminhoModulosTeste") as string; + const modulosPath = path.join(workspaceFolders[0].uri.fsPath, configPath); + + let directories: string[] = []; + try { + directories = await vscode.workspace.fs.readDirectory(vscode.Uri.file(modulosPath)) + .then(files => files + .filter(file => file[1] === vscode.FileType.Directory) + .map(file => file[0])); + } catch (error) { + console.error("Erro ao ler os módulos:", error); + return []; + } + + const modulosItems: ModuloItem[] = []; + + directories.forEach(directory => { + const modulePath = path.join(modulosPath, directory); + modulosItems.push(new ModuloItem(directory, vscode.TreeItemCollapsibleState.None, modulePath)); + }); + + return modulosItems; + } + } + getParent?(element: ModuloItem): vscode.ProviderResult { + throw new Error("Method not implemented."); + } + resolveTreeItem?(item: vscode.TreeItem, element: ModuloItem, token: vscode.CancellationToken): vscode.ProviderResult { + throw new Error("Method not implemented."); + } + + +} \ No newline at end of file diff --git a/src/providers/rotasProvider.ts b/src/providers/rotasProvider.ts new file mode 100644 index 0000000..014e25e --- /dev/null +++ b/src/providers/rotasProvider.ts @@ -0,0 +1,213 @@ +import * as vscode from "vscode"; +import { RotaInfo, RotaItem } from "../models/rotaModel"; +import * as path from "path"; +import * as fs from "fs"; +import type { FSWatcher } from "chokidar"; +import chokidar from "chokidar"; +import { getR3UtilsOutputChannel } from "../vscode/outputChannels/r3utils.outputchannel"; +export class RotasProvider implements vscode.TreeDataProvider { + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + + private readonly outputChannel = getR3UtilsOutputChannel(); + // private watchers: FSWatcher[] = []; + private watcher!: FSWatcher; + constructor() { + this.initializeWatchers(); + } + + private async initializeWatchers() { + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders) { + return; + } + + const configPath = vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos") as string; + const modulesPath = path.join(workspaceFolders[0].uri.fsPath, configPath); + + this.watcher = chokidar.watch(modulesPath, { + persistent: true, + ignoreInitial: false, + depth: 10, // Profundidade para monitorar subdiretórios + ignored: ['**/node_modules/**', '**/.git/**'] + }); + + this.watcher + .on('add', filePath => this.onFileChange(filePath, 'adicionado')) + .on('change', filePath => this.onFileChange(filePath, 'modificado')) + .on('unlink', filePath => this.onFileChange(filePath, 'removido')) + .on('addDir', dirPath => this.onDirChange(dirPath, 'adicionado')) + .on('unlinkDir', dirPath => this.onDirChange(dirPath, 'removido')); + + } + + private onFileChange(filePath: string, changeType: string) { + if (filePath.endsWith('.routes.ts')) { + const fileName = path.basename(filePath); + + this.createChannelMessage(` + Módulo: ${path.basename(path.dirname(filePath))}\n + Arquivo de rota ${changeType}: ${fileName}`); + this.refresh(); + } + } + + private onDirChange(dirPath: string, changeType: string) { + if (dirPath.includes(path.join('infra', 'data', 'routes'))) { + this.createChannelMessage(`Diretório de rotas ${changeType}: ${dirPath}`); + this.refresh(); + } + } + + refresh(): void { + this._onDidChangeTreeData.fire(); + } + getTreeItem(element: RotaItem): vscode.TreeItem | Thenable { + return element; + } + + private async findRouteFiles(dir: string): Promise { + let results: string[] = []; + const list = await fs.promises.readdir(dir, { withFileTypes: true }); + for (const file of list) { + const filePath = path.join(dir, file.name); + if (file.isDirectory()) { + results = results.concat(await this.findRouteFiles(filePath)); + } else if (file.isFile() && file.name.endsWith('.routes.ts')) { + results.push(filePath); + } + } + return results; + } + async getChildren(element?: RotaItem | undefined): Promise { + + if (element && element.children) { + return Promise.resolve(element.children); + + } else { + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders) { + return []; + } + + const configPath = vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos") as string; + const modulesPath = path.join(workspaceFolders[0].uri.fsPath, configPath); + // const modules = fs.readdirSync(modulesPath).filter(dir => fs.statSync(path.join(modulesPath, dir)).isDirectory()); + + let modules: string[] = []; + try { + const dirs = await fs.promises.readdir(modulesPath, { withFileTypes: true }); + modules = dirs.filter(dir => dir.isDirectory()).map(dir => dir.name); + } catch (error) { + console.error("Erro ao ler os módulos:", error); + return []; + } + + const rotas: RotaItem[] = []; + + for (const modulo of modules) { + const modulePath = path.join(modulesPath, modulo); + // caminho para o diretório de rotas do módulo + // const routesPath = path.join(modulesPath, modulo, "infra", "data", "routes"); + + try { + // obtendo os nomes dos arquivos do diretório de rotas + const files = await this.findRouteFiles(modulePath); + const rotaItems: RotaItem[] = []; + + for (const filePath of files) { + // if (file.endsWith('.routes.ts')) { + // const filePath = path.join(routesPath, file); + const content = await fs.promises.readFile(filePath, 'utf-8'); + + // Expressão regular atualizada + // const regex = /\.(get|post|put|delete)\(['"`](.*?)['"`]/g; + // const regex = /(?:\.(get|post|put|delete)\(['"`](.*?)['"`]\))|(?:server\.(get|post|put|delete)\s*\(\s*\{\s*routeName\s*:\s*['"`](.*?)['"`])/g; + // const regex = /(?:\.(get|post|put|delete)\(['"`](.*?)['"`]\))|(?:server\.(get|post|put|delete)\s*\(\s*\{\s*routeName\s*:\s*['"`](.*?)['"`])/g; + const regex = /(?:\.(get|post|put|delete)\(\s*['"`]([^'"`]+)['"`]\s*\))|(?:server\.(get|post|put|delete)\s*\(\s*\{[\s\S]*?routeName\s*:\s*['"`]([^'"`]+)['"`])/g; + let match; + + while ((match = regex.exec(content)) !== null) { + let method = ""; + let route = ""; + + if (match[1]) { + // Padrão: .get('/rota') + method = match[1].toUpperCase(); + route = match[2]; + } else if (match[3]) { + // Padrão: server.get({ routeName: '/rota', ... }) + method = match[3].toUpperCase(); + route = match[4]; + } + + // Calcula a posição dentro do arquivo + const lineNumber = content.substr(0, match.index).split('\n').length; + const rotaRange = new vscode.Range( + new vscode.Position(lineNumber, 0), + new vscode.Position(lineNumber, 0) + ); + + const rotaInfo = new RotaInfo(route, modulo, lineNumber, method, filePath, rotaRange); + + const rotaItem = new RotaItem( + rotaInfo, + vscode.TreeItemCollapsibleState.None, + undefined, + { + command: 'r3utils.rotas.openFile', + title: 'Abrir Arquivo', + arguments: [filePath, rotaRange] + } + ); + + rotaItems.push(rotaItem); + + } + } + + if (rotaItems.length > 0) { + rotas.push(new RotaItem( + new RotaInfo('', modulo, 0, undefined, undefined, undefined, modulePath), + vscode.TreeItemCollapsibleState.Collapsed, + rotaItems + )); + } + + } + catch (error) { + continue; + } + } + + return rotas; + + } + } + getParent?(element: RotaItem): vscode.ProviderResult { + throw new Error("Method not implemented."); + } + resolveTreeItem?(item: vscode.TreeItem, element: RotaItem, token: vscode.CancellationToken): vscode.ProviderResult { + throw new Error("Method not implemented."); + } + + private createChannelMessage(message: string): void { + this.outputChannel.appendLine(`${new Date().toLocaleTimeString([], { hour12: false })} ===== Rotas =====`); + if (message.includes('\n')) { + const trimmedMessage = message.split('\n') + .map(line => line.trim()) + .join('\n'); + this.outputChannel.appendLine(trimmedMessage); + } else { + this.outputChannel.appendLine(message.trim()); + } + this.outputChannel.appendLine('======================================'); + } + + + + dispose() { + this.watcher.close(); + } + +} \ No newline at end of file diff --git a/src/system/directories/moduloPath.ts b/src/system/directories/moduloPath.ts new file mode 100644 index 0000000..5138f02 --- /dev/null +++ b/src/system/directories/moduloPath.ts @@ -0,0 +1,41 @@ +import chokidar from "chokidar"; +import * as vscode from 'vscode'; +import type { ModuloModel } from "../../models/moduloModel"; + +export class ModuloPath implements ModuloModel { + private directoriesWatcher: chokidar.FSWatcher | undefined; + + constructor( + readonly path: string + ) { } + + watchDirectories(onChange: () => void): void { + if (this.directoriesWatcher) { + this.directoriesWatcher.close(); + } + + this.directoriesWatcher = chokidar.watch(this.path, { persistent: true }); + + this.directoriesWatcher.on("addDir", () => { + onChange(); + }); + + this.directoriesWatcher.on("unlinkDir", () => { + onChange(); + }); + } + + async getDirectories(): Promise { + const directories: string[] = []; + + const items = await vscode.workspace.fs.readDirectory(vscode.Uri.file(this.path)); + + for (const [name, type] of items) { + if (type === vscode.FileType.Directory) { + directories.push(name); + } + } + + return directories; + } +} \ No newline at end of file diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts new file mode 100644 index 0000000..5320dae --- /dev/null +++ b/src/test/extension.test.ts @@ -0,0 +1,39 @@ +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +import { ModulosProvider } from '../providers/modulosProvider'; +import { ModuloPath } from '../system/directories/moduloPath'; +// import * as myExtension from '../../extension'; + +suite('Extension Test Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + test('Sample test', () => { + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); + }); + + test("Deve ter propriedades configurações com valor padrão para o camiho de módulos", () => { + const expectedPathValue = "src/modules"; + const vscodePathValue = + vscode.workspace.getConfiguration("r3Utils").get("caminhoModulos"); + + console.log("vscodePathValue", vscodePathValue); + assert.strictEqual(expectedPathValue, expectedPathValue); + }); + + test("O provider de módulos deve retornar todos os diretórios do path", async () => { + // Set the configuration value before the test + await vscode.workspace.getConfiguration("r3Utils").update("caminhoModulosTeste", "testDirectory/modules", true); + + // obter o caminho para testDirectory a partir do arquivo atual + const pathValue = vscode.workspace.getConfiguration("r3Utils").get("caminhoModulosTeste"); + const diretorios = await new ModuloPath(pathValue as string); + console.log("Diretórios", diretorios); + const moduloProvider = new ModulosProvider(diretorios); + + console.log("children", moduloProvider.getChildren()); + }); +}); diff --git a/src/test/providers/modulosProvider.test.ts b/src/test/providers/modulosProvider.test.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/vscode/outputChannels/r3utils.outputchannel.ts b/src/vscode/outputChannels/r3utils.outputchannel.ts new file mode 100644 index 0000000..0d2bf83 --- /dev/null +++ b/src/vscode/outputChannels/r3utils.outputchannel.ts @@ -0,0 +1,7 @@ +import * as vscode from "vscode"; + +const outputChannel = vscode.window.createOutputChannel('r3Utils'); + +export function getR3UtilsOutputChannel() { + return outputChannel; +} \ No newline at end of file diff --git a/testDirectory/modules/conferenciaColetor/infra/data/routes/teste.routes.ts b/testDirectory/modules/conferenciaColetor/infra/data/routes/teste.routes.ts new file mode 100644 index 0000000..cc56c7f --- /dev/null +++ b/testDirectory/modules/conferenciaColetor/infra/data/routes/teste.routes.ts @@ -0,0 +1,5 @@ + +teste.get("/rotaTeste"); +teste.get("/rotaTeste2"); +teste.post("/postTeste3"); +teste.put("/putTeste4"); diff --git a/testDirectory/modules/conferenciaColetor/infra/data/routes/teste2.routes.ts b/testDirectory/modules/conferenciaColetor/infra/data/routes/teste2.routes.ts new file mode 100644 index 0000000..e69de29 diff --git a/testDirectory/modules/convocacaoAtiva/infra/data/routes/convocacaoAtiva.routes.ts b/testDirectory/modules/convocacaoAtiva/infra/data/routes/convocacaoAtiva.routes.ts new file mode 100644 index 0000000..385a0ec --- /dev/null +++ b/testDirectory/modules/convocacaoAtiva/infra/data/routes/convocacaoAtiva.routes.ts @@ -0,0 +1,3 @@ + + +convocacao.get("/obterConvocacao") \ No newline at end of file diff --git a/testDirectory/modules/moduControle/infra/data/routes/moduControle.routes.ts b/testDirectory/modules/moduControle/infra/data/routes/moduControle.routes.ts new file mode 100644 index 0000000..17cd149 --- /dev/null +++ b/testDirectory/modules/moduControle/infra/data/routes/moduControle.routes.ts @@ -0,0 +1,3 @@ + + +moduControle.get("/moduControle"); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5ee889b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "Node16", + "target": "ES2022", + "lib": [ + "ES2022" + ], + "sourceMap": true, + "rootDir": ".", + "strict": true /* enable all strict type-checking options */ + /* Additional Checks */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "testDirectory", + "**/*.spec.ts", + "**/*.test.ts" + ] +} \ No newline at end of file diff --git a/vsc-extension-quickstart.md b/vsc-extension-quickstart.md new file mode 100644 index 0000000..f518bb8 --- /dev/null +++ b/vsc-extension-quickstart.md @@ -0,0 +1,48 @@ +# Welcome to your VS Code Extension + +## What's in the folder + +* This folder contains all of the files necessary for your extension. +* `package.json` - this is the manifest file in which you declare your extension and command. + * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. +* `src/extension.ts` - this is the main file where you will provide the implementation of your command. + * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. + * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. + +## Setup + +* install the recommended extensions (amodio.tsl-problem-matcher, ms-vscode.extension-test-runner, and dbaeumer.vscode-eslint) + + +## Get up and running straight away + +* Press `F5` to open a new window with your extension loaded. +* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. +* Set breakpoints in your code inside `src/extension.ts` to debug your extension. +* Find output from your extension in the debug console. + +## Make changes + +* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. +* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. + + +## Explore the API + +* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. + +## Run tests + +* Install the [Extension Test Runner](https://marketplace.visualstudio.com/items?itemName=ms-vscode.extension-test-runner) +* Run the "watch" task via the **Tasks: Run Task** command. Make sure this is running, or tests might not be discovered. +* Open the Testing view from the activity bar and click the Run Test" button, or use the hotkey `Ctrl/Cmd + ; A` +* See the output of the test result in the Test Results view. +* Make changes to `src/test/extension.test.ts` or create new test files inside the `test` folder. + * The provided test runner will only consider files matching the name pattern `**.test.ts`. + * You can create folders inside the `test` folder to structure your tests any way you want. + +## Go further + +* Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). +* [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. +* Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).