vkdeploy-cli 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -0
- package/.eslintrc.json +13 -0
- package/.prettierignore +5 -0
- package/.prettierrc.json +5 -0
- package/.vscode/settings.json +3 -0
- package/.yarn/cache/@isaacs-cliui-npm-8.0.2-f4364666d5-4a473b9b32.zip +0 -0
- package/.yarn/cache/@isaacs-fs-minipass-npm-4.0.1-677026e841-5d36d28996.zip +0 -0
- package/.yarn/cache/@npmcli-agent-npm-3.0.0-169e79294f-e8fc25d536.zip +0 -0
- package/.yarn/cache/@npmcli-fs-npm-4.0.0-1d9cc8a27b-68951c589e.zip +0 -0
- package/.yarn/cache/@pkgjs-parseargs-npm-0.11.0-cd2a3fe948-6ad6a00fc4.zip +0 -0
- package/.yarn/cache/@realm-fetch-npm-0.1.1-76609d4244-4922bd005a.zip +0 -0
- package/.yarn/cache/abbrev-npm-3.0.0-946682a7b1-2500075b5e.zip +0 -0
- package/.yarn/cache/agent-base-npm-7.1.3-b2c16e72fb-87bb7ee54f.zip +0 -0
- package/.yarn/cache/ansi-regex-npm-5.0.1-c963a48615-2aa4bb54ca.zip +0 -0
- package/.yarn/cache/ansi-regex-npm-6.1.0-abe011aae4-495834a53b.zip +0 -0
- package/.yarn/cache/ansi-styles-npm-4.3.0-245c7d42c7-513b44c3b2.zip +0 -0
- package/.yarn/cache/ansi-styles-npm-6.2.1-d43647018c-ef940f2f0c.zip +0 -0
- package/.yarn/cache/asynckit-npm-0.4.0-c718858525-7b78c451df.zip +0 -0
- package/.yarn/cache/axios-npm-1.7.9-3c98466f87-cb8ce29181.zip +0 -0
- package/.yarn/cache/balanced-match-npm-1.0.2-a53c126459-9706c088a2.zip +0 -0
- package/.yarn/cache/base-64-npm-0.1.0-41e6da6777-5a42938f82.zip +0 -0
- package/.yarn/cache/base64-js-npm-1.5.1-b2f7275641-669632eb37.zip +0 -0
- package/.yarn/cache/bl-npm-4.1.0-7f94cdcf3f-9e8521fa7e.zip +0 -0
- package/.yarn/cache/brace-expansion-npm-2.0.1-17aa2616f9-a61e7cd2e8.zip +0 -0
- package/.yarn/cache/bson-npm-4.7.2-77a08a4d01-f357d12c56.zip +0 -0
- package/.yarn/cache/buffer-npm-5.7.1-513ef8259e-e2cf8429e1.zip +0 -0
- package/.yarn/cache/cacache-npm-19.0.1-395cba1936-e95684717d.zip +0 -0
- package/.yarn/cache/chalk-npm-5.3.0-d181999efb-623922e077.zip +0 -0
- package/.yarn/cache/chalk-npm-5.4.1-2f3fe4660a-0c656f30b7.zip +0 -0
- package/.yarn/cache/child_process-npm-1.0.2-04e116a38e-bd814d82bc.zip +0 -0
- package/.yarn/cache/chownr-npm-1.1.4-5bd400ab08-115648f8eb.zip +0 -0
- package/.yarn/cache/chownr-npm-3.0.0-5275e85d25-fd73a4bab4.zip +0 -0
- package/.yarn/cache/color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip +0 -0
- package/.yarn/cache/color-name-npm-1.1.4-025792b0ea-b044585952.zip +0 -0
- package/.yarn/cache/combined-stream-npm-1.0.8-dc14d4a63a-49fa4aeb49.zip +0 -0
- package/.yarn/cache/cross-spawn-npm-7.0.6-264bddf921-8d306efaca.zip +0 -0
- package/.yarn/cache/debug-npm-4.4.0-f6efe76023-fb42df878d.zip +0 -0
- package/.yarn/cache/decompress-response-npm-6.0.0-359de2878c-d377cf47e0.zip +0 -0
- package/.yarn/cache/deep-extend-npm-0.6.0-e182924219-7be7e5a8d4.zip +0 -0
- package/.yarn/cache/delayed-stream-npm-1.0.0-c5a4c4cc02-46fe6e83e2.zip +0 -0
- package/.yarn/cache/detect-libc-npm-2.0.3-2ddae34945-2ba6a939ae.zip +0 -0
- package/.yarn/cache/eastasianwidth-npm-0.2.0-c37eb16bd1-7d00d7cd8e.zip +0 -0
- package/.yarn/cache/emoji-regex-npm-8.0.0-213764015c-d4c5c39d5a.zip +0 -0
- package/.yarn/cache/emoji-regex-npm-9.2.2-e6fac8d058-8487182da7.zip +0 -0
- package/.yarn/cache/encoding-npm-0.1.13-82a1837d30-bb98632f8f.zip +0 -0
- package/.yarn/cache/end-of-stream-npm-1.4.4-497fc6dee1-530a5a5a1e.zip +0 -0
- package/.yarn/cache/env-paths-npm-2.2.1-7c7577428c-65b5df55a8.zip +0 -0
- package/.yarn/cache/err-code-npm-2.0.3-082e0ff9a7-8b7b1be20d.zip +0 -0
- package/.yarn/cache/events-npm-3.3.0-c280bc7e48-f6f487ad21.zip +0 -0
- package/.yarn/cache/expand-template-npm-2.0.3-80de959306-588c198472.zip +0 -0
- package/.yarn/cache/exponential-backoff-npm-3.1.1-04df458b30-3d21519a4f.zip +0 -0
- package/.yarn/cache/follow-redirects-npm-1.15.9-539785d34c-859e2bacc7.zip +0 -0
- package/.yarn/cache/foreground-child-npm-3.3.0-b8be745271-1989698488.zip +0 -0
- package/.yarn/cache/form-data-npm-4.0.1-f1a27a1c2e-ccee458cd5.zip +0 -0
- package/.yarn/cache/fs-constants-npm-1.0.0-59576b2177-18f5b71837.zip +0 -0
- package/.yarn/cache/fs-minipass-npm-3.0.3-d148d6ac19-8722a41109.zip +0 -0
- package/.yarn/cache/github-from-package-npm-0.0.0-519f80c9a1-14e448192a.zip +0 -0
- package/.yarn/cache/glob-npm-10.4.5-8c63175f05-0bc725de5e.zip +0 -0
- package/.yarn/cache/graceful-fs-npm-4.2.11-24bb648a68-ac85f94da9.zip +0 -0
- package/.yarn/cache/http-cache-semantics-npm-4.1.1-1120131375-83ac0bc60b.zip +0 -0
- package/.yarn/cache/http-proxy-agent-npm-7.0.2-643ed7cc33-670858c8f8.zip +0 -0
- package/.yarn/cache/https-proxy-agent-npm-7.0.6-27a95c2690-b882377a12.zip +0 -0
- package/.yarn/cache/iconv-lite-npm-0.6.3-24b8aae27e-3f60d47a5c.zip +0 -0
- package/.yarn/cache/ieee754-npm-1.2.1-fb63b3caeb-5144c0c981.zip +0 -0
- package/.yarn/cache/imurmurhash-npm-0.1.4-610c5068a0-7cae75c8cd.zip +0 -0
- package/.yarn/cache/inherits-npm-2.0.3-401e64b080-78cb8d7d85.zip +0 -0
- package/.yarn/cache/inherits-npm-2.0.4-c66b3957a0-4a48a73384.zip +0 -0
- package/.yarn/cache/ini-npm-1.3.8-fb5040b4c0-dfd98b0ca3.zip +0 -0
- package/.yarn/cache/ip-address-npm-9.0.5-9fa024d42a-aa15f12cfd.zip +0 -0
- package/.yarn/cache/is-fullwidth-code-point-npm-3.0.0-1ecf4ebee5-44a30c2945.zip +0 -0
- package/.yarn/cache/isexe-npm-2.0.0-b58870bd2e-26bf6c5480.zip +0 -0
- package/.yarn/cache/isexe-npm-3.1.1-9c0061eead-7fe1931ee4.zip +0 -0
- package/.yarn/cache/jackspeak-npm-3.4.3-546bfad080-be31027fc7.zip +0 -0
- package/.yarn/cache/jsbn-npm-1.1.0-1da0181838-944f924f2b.zip +0 -0
- package/.yarn/cache/lru-cache-npm-10.4.3-30c10b861a-6476138d21.zip +0 -0
- package/.yarn/cache/make-fetch-happen-npm-14.0.3-23b30e8691-6fb2fee6da.zip +0 -0
- package/.yarn/cache/mime-db-npm-1.52.0-b5371d6fd2-0d99a03585.zip +0 -0
- package/.yarn/cache/mime-types-npm-2.1.35-dd9ea9f3e2-89a5b7f1de.zip +0 -0
- package/.yarn/cache/mimic-response-npm-3.1.0-a4a24b4e96-25739fee32.zip +0 -0
- package/.yarn/cache/minimatch-npm-9.0.5-9aa93d97fa-2c035575ed.zip +0 -0
- package/.yarn/cache/minimist-npm-1.2.8-d7af7b1dce-75a6d645fb.zip +0 -0
- package/.yarn/cache/minipass-collect-npm-2.0.1-73d3907e40-b251bceea6.zip +0 -0
- package/.yarn/cache/minipass-fetch-npm-4.0.0-d4e49e0194-7d59a31011.zip +0 -0
- package/.yarn/cache/minipass-flush-npm-1.0.5-efe79d9826-56269a0b22.zip +0 -0
- package/.yarn/cache/minipass-npm-3.3.6-b8d93a945b-a30d083c80.zip +0 -0
- package/.yarn/cache/minipass-npm-7.1.2-3a5327d36d-2bfd325b95.zip +0 -0
- package/.yarn/cache/minipass-pipeline-npm-1.2.4-5924cb077f-b14240dac0.zip +0 -0
- package/.yarn/cache/minipass-sized-npm-1.0.3-306d86f432-79076749fc.zip +0 -0
- package/.yarn/cache/minizlib-npm-3.0.1-4bdabd978f-da0a538992.zip +0 -0
- package/.yarn/cache/mkdirp-classic-npm-0.5.3-3b5c991910-3f4e088208.zip +0 -0
- package/.yarn/cache/mkdirp-npm-3.0.1-f94bfa769e-972deb188e.zip +0 -0
- package/.yarn/cache/ms-npm-2.1.3-81ff3cfac1-aa92de6080.zip +0 -0
- package/.yarn/cache/napi-build-utils-npm-2.0.0-95da9c2e4e-532121efd2.zip +0 -0
- package/.yarn/cache/negotiator-npm-1.0.0-47d727e27e-20ebfe79b2.zip +0 -0
- package/.yarn/cache/node-abi-npm-3.73.0-299b8f8c39-d89bfe7b53.zip +0 -0
- package/.yarn/cache/node-gyp-npm-11.0.0-669e34db1b-d7d5055ccc.zip +0 -0
- package/.yarn/cache/node-machine-id-npm-1.1.12-ad6d29fa15-e23088a0fb.zip +0 -0
- package/.yarn/cache/nopt-npm-8.1.0-5570ef63cd-49cfd3eb6f.zip +0 -0
- package/.yarn/cache/once-npm-1.4.0-ccf03ef07a-cd0a885013.zip +0 -0
- package/.yarn/cache/p-map-npm-7.0.3-93bbec0d8c-8c92d533ac.zip +0 -0
- package/.yarn/cache/package-json-from-dist-npm-1.0.1-4631a88465-58ee9538f2.zip +0 -0
- package/.yarn/cache/path-browserify-npm-1.0.1-f975d99a99-c6d7fa3764.zip +0 -0
- package/.yarn/cache/path-key-npm-3.1.1-0e66ea8321-55cd7a9dd4.zip +0 -0
- package/.yarn/cache/path-npm-0.12.7-bddabe2e86-5dedb71e78.zip +0 -0
- package/.yarn/cache/path-scurry-npm-1.11.1-aaf8c339af-890d5abcd5.zip +0 -0
- package/.yarn/cache/prebuild-install-npm-7.1.3-8e79c3a0a2-300740ca41.zip +0 -0
- package/.yarn/cache/proc-log-npm-5.0.0-405173f9b4-c78b26ecef.zip +0 -0
- package/.yarn/cache/process-npm-0.11.10-aeb3b641ae-bfcce49814.zip +0 -0
- package/.yarn/cache/promise-retry-npm-2.0.1-871f0b01b7-f96a3f6d90.zip +0 -0
- package/.yarn/cache/proxy-from-env-npm-1.1.0-c13d07f26b-ed7fcc2ba0.zip +0 -0
- package/.yarn/cache/pump-npm-3.0.2-a8afc6734f-e0c4216874.zip +0 -0
- package/.yarn/cache/rc-npm-1.2.8-d6768ac936-2e26e052f8.zip +0 -0
- package/.yarn/cache/react-native-device-info-npm-14.0.2-04cf22684d-c1825a3151.zip +0 -0
- package/.yarn/cache/react-native-fs-npm-2.20.0-a38fe24051-0be9bb9a5c.zip +0 -0
- package/.yarn/cache/readable-stream-npm-3.6.2-d2a6069158-bdcbe6c22e.zip +0 -0
- package/.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-623bd7d2e5.zip +0 -0
- package/.yarn/cache/rimraf-npm-5.0.10-d0c6647697-50e27388dd.zip +0 -0
- package/.yarn/cache/safe-buffer-npm-5.2.1-3481c8aa9b-b99c4b41fd.zip +0 -0
- package/.yarn/cache/safer-buffer-npm-2.1.2-8d5c0b705e-cab8f25ae6.zip +0 -0
- package/.yarn/cache/sax-npm-1.4.1-503b1923cb-3ad64df16b.zip +0 -0
- package/.yarn/cache/semver-npm-7.6.3-57e82c14d5-4110ec5d01.zip +0 -0
- package/.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-6b52fe8727.zip +0 -0
- package/.yarn/cache/shebang-regex-npm-3.0.0-899a0cd65e-1a2bcae50d.zip +0 -0
- package/.yarn/cache/signal-exit-npm-4.1.0-61fb957687-64c757b498.zip +0 -0
- package/.yarn/cache/simple-concat-npm-1.0.1-48df70de29-4d211042cc.zip +0 -0
- package/.yarn/cache/simple-get-npm-4.0.1-fa2a97645d-e4132fd27c.zip +0 -0
- package/.yarn/cache/smart-buffer-npm-4.2.0-5ac3f668bb-b5167a7142.zip +0 -0
- package/.yarn/cache/socks-npm-2.8.3-3532b59899-7a6b7f6eed.zip +0 -0
- package/.yarn/cache/socks-proxy-agent-npm-8.0.5-24d77a90dc-b4fbcdb7ad.zip +0 -0
- package/.yarn/cache/sprintf-js-npm-1.1.3-b99efd75b2-a3fdac7b49.zip +0 -0
- package/.yarn/cache/ssri-npm-12.0.0-97c0e53d2e-ef4b6b0ae4.zip +0 -0
- package/.yarn/cache/string-width-npm-4.2.3-2c27177bae-e52c10dc3f.zip +0 -0
- package/.yarn/cache/string-width-npm-5.1.2-bf60531341-7369deaa29.zip +0 -0
- package/.yarn/cache/string_decoder-npm-1.3.0-2422117fd0-8417646695.zip +0 -0
- package/.yarn/cache/strip-ansi-npm-6.0.1-caddc7cb40-f3cd25890a.zip +0 -0
- package/.yarn/cache/strip-ansi-npm-7.1.0-7453b80b79-859c73fcf2.zip +0 -0
- package/.yarn/cache/strip-json-comments-npm-2.0.1-e7883b2d04-1074ccb632.zip +0 -0
- package/.yarn/cache/tar-fs-npm-2.1.2-4231292dd1-6b4fcd38a6.zip +0 -0
- package/.yarn/cache/tar-npm-7.4.3-1dbbd1ffc3-8485350c06.zip +0 -0
- package/.yarn/cache/tar-stream-npm-2.2.0-884c79b510-699831a8b9.zip +0 -0
- package/.yarn/cache/timers-npm-0.1.1-caf37d810c-3f75b95c19.zip +0 -0
- package/.yarn/cache/tunnel-agent-npm-0.6.0-64345ab7eb-05f6510358.zip +0 -0
- package/.yarn/cache/unique-filename-npm-4.0.0-bfc100c4e3-6a62094fca.zip +0 -0
- package/.yarn/cache/unique-slug-npm-5.0.0-11508c0469-222d0322bc.zip +0 -0
- package/.yarn/cache/utf8-npm-3.0.0-7c39b5994a-cb89a69ad9.zip +0 -0
- package/.yarn/cache/util-deprecate-npm-1.0.2-e3fe1a219c-474acf1146.zip +0 -0
- package/.yarn/cache/util-npm-0.10.4-7c577db41a-913f9a90d0.zip +0 -0
- package/.yarn/cache/which-npm-2.0.2-320ddf72f7-1a5c563d3c.zip +0 -0
- package/.yarn/cache/which-npm-5.0.0-15aa39eb60-6ec99e89ba.zip +0 -0
- package/.yarn/cache/wrap-ansi-npm-7.0.0-ad6e1a0554-a790b846fd.zip +0 -0
- package/.yarn/cache/wrap-ansi-npm-8.1.0-26a4e6ae28-371733296d.zip +0 -0
- package/.yarn/cache/wrappy-npm-1.0.2-916de4d4b3-159da4805f.zip +0 -0
- package/.yarn/cache/xml2js-npm-0.6.2-64cd781d74-458a838061.zip +0 -0
- package/.yarn/cache/xmlbuilder-npm-11.0.1-b8b04dc929-7152695e16.zip +0 -0
- package/.yarn/cache/yallist-npm-4.0.0-b493d9e907-343617202a.zip +0 -0
- package/.yarn/cache/yallist-npm-5.0.0-8732dd9f1c-eba5118240.zip +0 -0
- package/.yarn/install-state.gz +0 -0
- package/README.md +191 -0
- package/bin/bundle.js +260 -0
- package/bin/cli.js +101 -0
- package/index.js +0 -0
- package/package.json +43 -0
- package/src/Login.js +8 -0
- package/src/config/env.js +64 -0
- package/utils/functions.js +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# vkdeploy-cli
|
|
2
|
+
|
|
3
|
+
CLI em Node.js para gerar o bundle de um app React Native, compactar os assets e enviar o arquivo para o backend de versionamento.
|
|
4
|
+
|
|
5
|
+
## O que esse projeto faz
|
|
6
|
+
|
|
7
|
+
O `vkdeploy` automatiza o fluxo de publicação de bundle:
|
|
8
|
+
|
|
9
|
+
1. abre o fluxo de login para o usuário obter um token;
|
|
10
|
+
2. salva o token localmente;
|
|
11
|
+
3. gera o bundle React Native Android;
|
|
12
|
+
4. compacta bundle + assets em um `.zip`;
|
|
13
|
+
5. lê a configuração do projeto React Native;
|
|
14
|
+
6. envia o arquivo para a API de versionamento.
|
|
15
|
+
|
|
16
|
+
## Requisitos
|
|
17
|
+
|
|
18
|
+
- Node.js `>=18`
|
|
19
|
+
- `zip` instalado no sistema
|
|
20
|
+
- projeto React Native com pasta `android/`
|
|
21
|
+
- arquivo `android/app/src/main/assets/vkdeploy-config.json`
|
|
22
|
+
|
|
23
|
+
Exemplo mínimo do arquivo de configuração:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"app_secret": "SEU_APP_SECRET"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Instalação
|
|
32
|
+
|
|
33
|
+
### Desenvolvimento local com link
|
|
34
|
+
|
|
35
|
+
Dentro deste projeto:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install
|
|
39
|
+
npm link
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Depois disso, o comando global `vkdeploy` passa a apontar para o código local. Qualquer alteração no código já entra na próxima execução.
|
|
43
|
+
|
|
44
|
+
### Instalação global
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuração de ambiente
|
|
51
|
+
|
|
52
|
+
O projeto lê variáveis de ambiente de:
|
|
53
|
+
|
|
54
|
+
- `process.env`
|
|
55
|
+
- arquivo local `.env`
|
|
56
|
+
- fallback definido no código
|
|
57
|
+
|
|
58
|
+
Arquivo de exemplo: [.env.example](/home/vinikir/Projetos/Versionamento/vkdeploy-cli/.env.example:1)
|
|
59
|
+
|
|
60
|
+
Variáveis disponíveis:
|
|
61
|
+
|
|
62
|
+
- `FRONTEND_BASE_URL`: base usada para abrir a página de login
|
|
63
|
+
- `API_BASE_URL`: base usada para enviar o bundle para o backend
|
|
64
|
+
|
|
65
|
+
Exemplo:
|
|
66
|
+
|
|
67
|
+
```env
|
|
68
|
+
FRONTEND_BASE_URL=http://localhost:3000
|
|
69
|
+
API_BASE_URL=http://localhost:3300
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Comandos
|
|
73
|
+
|
|
74
|
+
### `vkdeploy login`
|
|
75
|
+
|
|
76
|
+
Abre a URL de login no navegador e pede o token no terminal.
|
|
77
|
+
|
|
78
|
+
Fluxo atual:
|
|
79
|
+
|
|
80
|
+
1. abre a URL montada a partir de `FRONTEND_BASE_URL`;
|
|
81
|
+
2. solicita `Insira o token gerado:`;
|
|
82
|
+
3. salva o token em `database/loginStatus.json`.
|
|
83
|
+
|
|
84
|
+
### `vkdeploy release-react <projeto> <os>`
|
|
85
|
+
|
|
86
|
+
Executa o fluxo de geração e upload do bundle.
|
|
87
|
+
|
|
88
|
+
Exemplo:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
vkdeploy release-react "Teste REAL" android
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Fluxo atual:
|
|
95
|
+
|
|
96
|
+
1. verifica se existe login salvo;
|
|
97
|
+
2. gera o bundle em `./temp/vkdeploy`;
|
|
98
|
+
3. compacta os arquivos em `bundle-assets.zip`;
|
|
99
|
+
4. lê `app_secret` de `android/app/src/main/assets/vkdeploy-config.json`;
|
|
100
|
+
5. lê `versionName` de `android/app/build.gradle`;
|
|
101
|
+
6. envia o zip para backend;
|
|
102
|
+
7. remove arquivos temporários.
|
|
103
|
+
|
|
104
|
+
## Scripts de qualidade
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm run lint
|
|
108
|
+
npm run lint:fix
|
|
109
|
+
npm run format
|
|
110
|
+
npm run format:check
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Estrutura do projeto
|
|
114
|
+
|
|
115
|
+
```txt
|
|
116
|
+
bin/
|
|
117
|
+
cli.js
|
|
118
|
+
bundle.js
|
|
119
|
+
src/
|
|
120
|
+
Login.js
|
|
121
|
+
config/
|
|
122
|
+
env.js
|
|
123
|
+
database/
|
|
124
|
+
loginStatus.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Funções principais
|
|
128
|
+
|
|
129
|
+
Responsável por montar os comandos do CLI com `yargs`.
|
|
130
|
+
|
|
131
|
+
Funções:
|
|
132
|
+
|
|
133
|
+
- `ensureDatabaseDirExists()`: cria o diretório de persistência do login, se ele não existir
|
|
134
|
+
- `isLoggedIn()`: verifica se existe status de login salvo no JSON
|
|
135
|
+
|
|
136
|
+
Comandos:
|
|
137
|
+
|
|
138
|
+
- `login`: abre o fluxo de autenticação e persiste o token
|
|
139
|
+
- `release-react`: dispara a geração e o upload do bundle
|
|
140
|
+
|
|
141
|
+
Responsável pela parte operacional do release.
|
|
142
|
+
|
|
143
|
+
Funções:
|
|
144
|
+
|
|
145
|
+
- `deleteFolderRecursive(folderPath)`: remove diretórios e arquivos recursivamente
|
|
146
|
+
- `buscProjetoId()`: lê o `app_secret` do arquivo `vkdeploy-config.json`
|
|
147
|
+
- `generateBundle()`: executa o comando `react-native bundle`
|
|
148
|
+
- `pegaVersionName()`: extrai o `versionName` do `build.gradle`
|
|
149
|
+
- `CompactarArquivos()`: gera o `bundle-assets.zip`
|
|
150
|
+
- `UploadBundle()`: envia o zip para a API
|
|
151
|
+
- `hashFileSha256(filePath)`: calcula o hash SHA-256 do arquivo gerado
|
|
152
|
+
- `toMb(bytes)`: converte bytes para MB para exibição no terminal
|
|
153
|
+
|
|
154
|
+
Responsável por centralizar a configuração de URLs.
|
|
155
|
+
|
|
156
|
+
Funções internas:
|
|
157
|
+
|
|
158
|
+
- `parseEnvFile(fileContent)`: interpreta o conteúdo do `.env`
|
|
159
|
+
- `getEnvValue(key, fallback)`: lê da variável de ambiente, do `.env` local ou do fallback
|
|
160
|
+
- `normalizeBaseUrl(value)`: remove `/` no fim da base URL
|
|
161
|
+
- `buildUrl(baseUrl, pathname)`: monta a URL final
|
|
162
|
+
|
|
163
|
+
Valores exportados:
|
|
164
|
+
|
|
165
|
+
- `FRONTEND_BASE_URL`
|
|
166
|
+
- `API_BASE_URL`
|
|
167
|
+
- `LOGIN_URL`
|
|
168
|
+
- `UPLOAD_BUNDLE_URL`
|
|
169
|
+
|
|
170
|
+
Responsável por abrir no navegador a URL de login calculada em `env.js`.
|
|
171
|
+
|
|
172
|
+
Função:
|
|
173
|
+
|
|
174
|
+
- `login()`: abre `LOGIN_URL`
|
|
175
|
+
|
|
176
|
+
## Tratamento de erro implementado
|
|
177
|
+
|
|
178
|
+
Hoje o CLI já valida alguns pontos antes do upload:
|
|
179
|
+
|
|
180
|
+
- ausência de `vkdeploy-config.json`
|
|
181
|
+
- JSON inválido em `vkdeploy-config.json`
|
|
182
|
+
- ausência de `app_secret`
|
|
183
|
+
- ausência de `bundle-assets.zip`
|
|
184
|
+
- ausência de `versionName` no `build.gradle`
|
|
185
|
+
|
|
186
|
+
## Limitações atuais
|
|
187
|
+
|
|
188
|
+
- o token ainda é salvo dentro do projeto, em `database/loginStatus.json`
|
|
189
|
+
- o fluxo de upload ainda não envia o token salvo para a API
|
|
190
|
+
- o código hoje está preparado principalmente para Android
|
|
191
|
+
- há pontos de refatoração pendentes no fluxo assíncrono de `bundle.js`
|
package/bin/bundle.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import FormData from "form-data";
|
|
4
|
+
import { exec } from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import crypto from "crypto";
|
|
8
|
+
import { UPLOAD_BUNDLE_URL } from "../src/config/env.js";
|
|
9
|
+
|
|
10
|
+
const tmpDir = path.resolve("./temp");
|
|
11
|
+
const versionamentoClubeDir = path.resolve(tmpDir, "vkdeploy");
|
|
12
|
+
let jaExistiaPastaTemp = false;
|
|
13
|
+
|
|
14
|
+
const toMb = (bytes) => (bytes / (1024 * 1024)).toFixed(2);
|
|
15
|
+
|
|
16
|
+
const hashFileSha256 = (filePath) =>
|
|
17
|
+
new Promise((resolve, reject) => {
|
|
18
|
+
const hash = crypto.createHash("sha256");
|
|
19
|
+
const stream = fs.createReadStream(filePath);
|
|
20
|
+
|
|
21
|
+
stream.on("error", reject);
|
|
22
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
23
|
+
stream.on("end", () => resolve(hash.digest("hex")));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const deleteFolderRecursive = (folderPath) => {
|
|
27
|
+
if (fs.existsSync(folderPath)) {
|
|
28
|
+
fs.readdirSync(folderPath).forEach((file) => {
|
|
29
|
+
const curPath = path.join(folderPath, file);
|
|
30
|
+
|
|
31
|
+
if (fs.lstatSync(curPath).isDirectory()) {
|
|
32
|
+
deleteFolderRecursive(curPath);
|
|
33
|
+
} else {
|
|
34
|
+
fs.unlinkSync(curPath);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
fs.rmdirSync(folderPath);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const buscProjetoId = async () => {
|
|
43
|
+
const configFilePath = path.resolve(
|
|
44
|
+
"./android/app/src/main/assets/vkdeploy-config.json"
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (!fs.existsSync(configFilePath)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
[
|
|
50
|
+
"Arquivo de configuração não encontrado.",
|
|
51
|
+
`Crie o arquivo em: ${configFilePath}`,
|
|
52
|
+
'Conteúdo mínimo esperado: {"app_secret":"SEU_APP_SECRET"}',
|
|
53
|
+
].join("\n")
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const fileContent = fs.readFileSync(configFilePath, "utf8");
|
|
58
|
+
let jsonData;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
jsonData = JSON.parse(fileContent);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Arquivo de configuração inválido em ${configFilePath}: JSON mal formatado.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
typeof jsonData.app_secret !== "string" ||
|
|
70
|
+
jsonData.app_secret.trim() === ""
|
|
71
|
+
) {
|
|
72
|
+
throw new Error(`O campo "app_secret" é obrigatório em ${configFilePath}.`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return jsonData.app_secret.trim();
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const generateBundle = async () => {
|
|
79
|
+
try {
|
|
80
|
+
console.log(chalk.blue(`📦 Gerando o bundle ...`), "\n");
|
|
81
|
+
//const command = `npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res`;
|
|
82
|
+
const command = `npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./temp/vkdeploy/index.android.bundle --assets-dest ./temp/vkdeploy`;
|
|
83
|
+
//const command = `npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./temp/vkdeploy/index.android.bundle --assets-dest ./temp/vkdeploy/assets`
|
|
84
|
+
//const command = `ls`;
|
|
85
|
+
|
|
86
|
+
if (!fs.existsSync(tmpDir)) {
|
|
87
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
88
|
+
} else {
|
|
89
|
+
jaExistiaPastaTemp = true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!fs.existsSync(versionamentoClubeDir)) {
|
|
93
|
+
fs.mkdirSync(versionamentoClubeDir, { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
exec(command, (error, stdout, stderr) => {
|
|
97
|
+
if (
|
|
98
|
+
error &&
|
|
99
|
+
error.message !=
|
|
100
|
+
`warn Package react-native-sqlite-storage contains invalid configuration: "dependency.platforms.ios.project" is not allowed. Please verify it's properly linked using "npx react-native config" command and contact the package maintainers about this.`
|
|
101
|
+
) {
|
|
102
|
+
console.log(
|
|
103
|
+
chalk.red(`❌ Erro: Falha ao gerar o bundle: ${error.message}`)
|
|
104
|
+
);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (stderr) {
|
|
109
|
+
console.log(chalk.yellow(`💡 Aviso: ${stderr}`));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log(chalk.green("✅ O bundle foi gerado com sucesso!"), "\n");
|
|
113
|
+
CompactarArquivos();
|
|
114
|
+
});
|
|
115
|
+
} catch (e) {
|
|
116
|
+
deleteFolderRecursive(versionamentoClubeDir);
|
|
117
|
+
if (!jaExistiaPastaTemp) {
|
|
118
|
+
deleteFolderRecursive("temp");
|
|
119
|
+
}
|
|
120
|
+
console.log(
|
|
121
|
+
chalk.red(`❌ Erro: Falha ao gerar o bundle: ${e.message}`),
|
|
122
|
+
"\n"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const pegaVersionName = () => {
|
|
127
|
+
try {
|
|
128
|
+
const gradleFilePath = "./android/app/build.gradle";
|
|
129
|
+
|
|
130
|
+
const gradleFileContent = fs.readFileSync(gradleFilePath, "utf-8");
|
|
131
|
+
|
|
132
|
+
const versionNameMatch = gradleFileContent.match(/versionName\s+"([^"]+)"/);
|
|
133
|
+
|
|
134
|
+
if (versionNameMatch && versionNameMatch[1]) {
|
|
135
|
+
const versionName = versionNameMatch[1];
|
|
136
|
+
|
|
137
|
+
return versionName;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
throw new Error("Atributo versionName não encontrado no arquivo.");
|
|
141
|
+
} catch (e) {
|
|
142
|
+
throw new Error(e.message);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const CompactarArquivos = async () => {
|
|
147
|
+
try {
|
|
148
|
+
//index.android.bundle
|
|
149
|
+
//const command2 = `tar -czvf bundle-assets.tar -C android/app/src/main assets/index.android.bundle res`;
|
|
150
|
+
//const command2 = `cd android/app/src/main && zip -r ../../../../bundle-assets.zip assets/index.android.bundle res && cd ../../../../`;
|
|
151
|
+
//const command2 = `zip -r bundle-assets.zip temp/vkdeploy/*`;
|
|
152
|
+
const command2 = `cd temp/vkdeploy && zip -r ../../bundle-assets.zip * && cd ../../`;
|
|
153
|
+
|
|
154
|
+
console.log(chalk.blue(`🗃️ Empacotando o bundle e os assets ...`), "\n");
|
|
155
|
+
|
|
156
|
+
exec(command2, (error, stdout, stderr) => {
|
|
157
|
+
if (error) {
|
|
158
|
+
console.log(
|
|
159
|
+
chalk.red(
|
|
160
|
+
`❌ Erro: Falha ao gerar o empacotamento do bundle e assets : ${error.message}`
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (stderr) {
|
|
167
|
+
console.log(chalk.yellow(`💡 Aviso: ${stderr}`));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.log(
|
|
171
|
+
chalk.green("✅ O bundle e os assets foram empacotados com sucesso!"),
|
|
172
|
+
"\n"
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
deleteFolderRecursive(versionamentoClubeDir);
|
|
176
|
+
if (!jaExistiaPastaTemp) {
|
|
177
|
+
deleteFolderRecursive("temp");
|
|
178
|
+
}
|
|
179
|
+
UploadBundle();
|
|
180
|
+
});
|
|
181
|
+
// UploadBundle();
|
|
182
|
+
} catch (e) {
|
|
183
|
+
deleteFolderRecursive(versionamentoClubeDir);
|
|
184
|
+
if (!jaExistiaPastaTemp) {
|
|
185
|
+
deleteFolderRecursive("temp");
|
|
186
|
+
}
|
|
187
|
+
deleteFolderRecursive("bundle-assets.zip");
|
|
188
|
+
throw new Error(e.message);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const UploadBundle = async () => {
|
|
193
|
+
try {
|
|
194
|
+
console.log(chalk.blue(`📤 Upload do bundle...`), "\n");
|
|
195
|
+
|
|
196
|
+
const projectId = await buscProjetoId();
|
|
197
|
+
//const filePath = "./android/app/src/main/assets/index.android.bundle"
|
|
198
|
+
const filePath = "./bundle-assets.zip";
|
|
199
|
+
|
|
200
|
+
if (!fs.existsSync(filePath)) {
|
|
201
|
+
throw new Error(`Arquivo de upload não encontrado: ${filePath}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const zipStats = fs.statSync(filePath);
|
|
205
|
+
const zipHash = await hashFileSha256(filePath);
|
|
206
|
+
const zipAbsolutePath = path.resolve(filePath);
|
|
207
|
+
|
|
208
|
+
console.log(chalk.blue("🧾 Validando arquivo de upload..."), "\n");
|
|
209
|
+
console.log(`Arquivo: ${path.basename(filePath)}`);
|
|
210
|
+
console.log(`Caminho: ${zipAbsolutePath}`);
|
|
211
|
+
console.log(`Tamanho: ${zipStats.size} bytes (${toMb(zipStats.size)} MB)`);
|
|
212
|
+
console.log(`SHA256: ${zipHash}`, "\n");
|
|
213
|
+
|
|
214
|
+
const uploadUrl = UPLOAD_BUNDLE_URL;
|
|
215
|
+
|
|
216
|
+
const fileStream = fs.createReadStream(filePath);
|
|
217
|
+
|
|
218
|
+
const versionBundle = pegaVersionName();
|
|
219
|
+
|
|
220
|
+
const formData = new FormData();
|
|
221
|
+
|
|
222
|
+
formData.append("projeto", projectId);
|
|
223
|
+
formData.append("versaoBuild", versionBundle);
|
|
224
|
+
|
|
225
|
+
formData.append("file", fileStream);
|
|
226
|
+
let versaoUltima;
|
|
227
|
+
|
|
228
|
+
await axios
|
|
229
|
+
.post(uploadUrl, formData, {
|
|
230
|
+
headers: {
|
|
231
|
+
...formData.getHeaders(),
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
.then((res) => {
|
|
235
|
+
versaoUltima = res.data.versao;
|
|
236
|
+
})
|
|
237
|
+
.catch((e) => {
|
|
238
|
+
console.log("Errroooo", JSON.stringify(e));
|
|
239
|
+
fs.unlinkSync(filePath);
|
|
240
|
+
throw new Error(e.message);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
console.log(chalk.green("✅ O upload foi realizado com sucesso!"), "\n");
|
|
244
|
+
console.log(
|
|
245
|
+
chalk.green(
|
|
246
|
+
`Versão publicada: Android ${versionBundle}, bundle ${versaoUltima} (V ${versionBundle}.${versaoUltima})`
|
|
247
|
+
),
|
|
248
|
+
"\n"
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
fs.unlinkSync(filePath);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.log(
|
|
254
|
+
chalk.red(`❌ Erro: Falha ao fazer upload do bundle: ${error.message}`),
|
|
255
|
+
"\n"
|
|
256
|
+
);
|
|
257
|
+
} finally {
|
|
258
|
+
deleteFolderRecursive("bundle-assets.zip");
|
|
259
|
+
}
|
|
260
|
+
};
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from "yargs/yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
import { generateBundle } from "./bundle.js";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import login from "../src/Login.js";
|
|
9
|
+
import readline from "readline";
|
|
10
|
+
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Ajuste o caminho para salvar o arquivo na pasta 'database' uma pasta atrás
|
|
17
|
+
const loginFilePath = path.resolve(__dirname, "../database/loginStatus.json");
|
|
18
|
+
|
|
19
|
+
const ensureDatabaseDirExists = () => {
|
|
20
|
+
const dir = path.dirname(loginFilePath);
|
|
21
|
+
if (!fs.existsSync(dir)) {
|
|
22
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
// async function login() {
|
|
26
|
+
// // Função para fazer o login
|
|
27
|
+
// console.log("Realizando login...");
|
|
28
|
+
// // Adicione aqui a lógica de login
|
|
29
|
+
|
|
30
|
+
// // Simulando login bem-sucedido
|
|
31
|
+
// const loginStatus = { loggedIn: true };
|
|
32
|
+
// fs.writeFileSync(loginFilePath, JSON.stringify(loginStatus));
|
|
33
|
+
// console.log("Login realizado com sucesso.");
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
function isLoggedIn() {
|
|
37
|
+
if (fs.existsSync(loginFilePath)) {
|
|
38
|
+
const loginStatus = JSON.parse(fs.readFileSync(loginFilePath, "utf-8"));
|
|
39
|
+
return loginStatus.loggedIn;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
yargs(hideBin(process.argv))
|
|
45
|
+
.command(
|
|
46
|
+
"release-react [projeto]",
|
|
47
|
+
"Gera bundle e faz upload",
|
|
48
|
+
(yargs) => {
|
|
49
|
+
return yargs
|
|
50
|
+
.positional("projeto", {
|
|
51
|
+
describe: "Projeto alvo",
|
|
52
|
+
default: "meu-projeto",
|
|
53
|
+
})
|
|
54
|
+
.positional("os", {
|
|
55
|
+
describe: "OS alvo",
|
|
56
|
+
default: "android",
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
async (argv) => {
|
|
60
|
+
console.log(isLoggedIn());
|
|
61
|
+
if (!isLoggedIn()) {
|
|
62
|
+
console.log("Você precisa estar logado para gerar o bundle.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (argv.os == "android") {
|
|
67
|
+
console.log(`Gerando bundle para ${argv.projeto} os ${argv.os} `, "\n");
|
|
68
|
+
await generateBundle();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (argv.os == "ios") {
|
|
72
|
+
console.log(`Gerando bundle para ${argv.projeto} os ${argv.os} `, "\n");
|
|
73
|
+
//await generateBundleIOS()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
.command(
|
|
78
|
+
"login",
|
|
79
|
+
"Realiza login",
|
|
80
|
+
(yargs) => {
|
|
81
|
+
return yargs;
|
|
82
|
+
},
|
|
83
|
+
async () => {
|
|
84
|
+
login();
|
|
85
|
+
const rl = readline.createInterface({
|
|
86
|
+
input: process.stdin,
|
|
87
|
+
output: process.stdout,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
rl.question("Insira o token gerado: ", (token) => {
|
|
91
|
+
// Simulando login bem-sucedido com o token
|
|
92
|
+
const loginStatus = { loggedIn: true, token: token };
|
|
93
|
+
ensureDatabaseDirExists();
|
|
94
|
+
fs.writeFileSync(loginFilePath, JSON.stringify(loginStatus));
|
|
95
|
+
console.log("Login realizado com sucesso.");
|
|
96
|
+
rl.close();
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
.help()
|
|
101
|
+
.parse();
|
package/index.js
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vkdeploy-cli",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"lint": "eslint .",
|
|
7
|
+
"lint:fix": "eslint . --fix",
|
|
8
|
+
"format": "prettier . --write",
|
|
9
|
+
"format:check": "prettier . --check",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"description": "",
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"fs": "^0.0.1-security",
|
|
17
|
+
"react": "18.3.1"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"vkdeploy": "./bin/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.7.9",
|
|
24
|
+
"chalk": "^5.3.0",
|
|
25
|
+
"child_process": "^1.0.2",
|
|
26
|
+
"events": "^3.3.0",
|
|
27
|
+
"form-data": "^4.0.1",
|
|
28
|
+
"open": "^10.1.0",
|
|
29
|
+
"path": "^0.12.7",
|
|
30
|
+
"readline": "^1.3.0",
|
|
31
|
+
"timers": "^0.1.1",
|
|
32
|
+
"xml2js": "^0.6.2",
|
|
33
|
+
"yargs": "^17.7.2"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"eslint": "^8.57.1",
|
|
37
|
+
"prettier": "^3.3.3"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"type": "module"
|
|
43
|
+
}
|
package/src/Login.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const rootDir = path.resolve(__dirname, "../..");
|
|
8
|
+
const envFilePath = path.join(rootDir, ".env");
|
|
9
|
+
|
|
10
|
+
const parseEnvFile = (fileContent) => {
|
|
11
|
+
const env = {};
|
|
12
|
+
|
|
13
|
+
for (const rawLine of fileContent.split(/\r?\n/)) {
|
|
14
|
+
const line = rawLine.trim();
|
|
15
|
+
|
|
16
|
+
if (!line || line.startsWith("#")) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const separatorIndex = line.indexOf("=");
|
|
21
|
+
|
|
22
|
+
if (separatorIndex === -1) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
27
|
+
let value = line.slice(separatorIndex + 1).trim();
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
31
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
32
|
+
) {
|
|
33
|
+
value = value.slice(1, -1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
env[key] = value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return env;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const fileEnv = fs.existsSync(envFilePath)
|
|
43
|
+
? parseEnvFile(fs.readFileSync(envFilePath, "utf-8"))
|
|
44
|
+
: {};
|
|
45
|
+
|
|
46
|
+
const getEnvValue = (key, fallback) =>
|
|
47
|
+
process.env[key] || fileEnv[key] || fallback;
|
|
48
|
+
|
|
49
|
+
const normalizeBaseUrl = (value) => value.replace(/\/+$/, "");
|
|
50
|
+
|
|
51
|
+
const buildUrl = (baseUrl, pathname) =>
|
|
52
|
+
`${normalizeBaseUrl(baseUrl)}${pathname}`;
|
|
53
|
+
|
|
54
|
+
export const FRONTEND_BASE_URL = getEnvValue(
|
|
55
|
+
"FRONTEND_BASE_URL",
|
|
56
|
+
"http://localhost:3000"
|
|
57
|
+
);
|
|
58
|
+
export const API_BASE_URL = getEnvValue(
|
|
59
|
+
"API_BASE_URL",
|
|
60
|
+
"https://versionamento-back-end-388770734965.us-central1.run.app"
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export const LOGIN_URL = buildUrl(FRONTEND_BASE_URL, "/token");
|
|
64
|
+
export const UPLOAD_BUNDLE_URL = buildUrl(API_BASE_URL, "/bundle/uploadFile");
|
|
File without changes
|