@autoaction/vbn-node-client
v1.0.6
Published
VBN para NodeJs. Load Balance + CDN + bucket privado + url's assinadas (GCP)
Maintainers
Readme
Permissão de usuário necessária
É necessário que o usuário que vai acessar o GCP tenha essa permissão, caso contrário o cache não poderá ser invalidado
compute.urlMaps.invalidateCacheCertifique-se que o bucket está mapeado em um Load Balancer no GCP
Consulte o Notion específico para realizar as etapas abaixo: :: Acesse o Load Balancer :: Cria um backend de Bucket :: Crie o mapeamento do backent e o bucket
Em caso de atualização da lib
:: Fazer o push dentro da branch master :: criar uma tag vxxxxx (Ex: v1.0.8)
git tag v1.0.8:: Fazer o push da tag
git push origin v1.0.8Documento do Client para VBN
Inspirado em DSL(Domain Specific Language) internas, para controle e solicitação fluída
Abaixo um exemplo prático de um helper para implantar o projeto
Fase de configuração
const { VBNAutoAction, VBNUtils } = require('vbn-node-client');
class VBNHelper extends VBNAutoAction {
static VBN_PROD_URL = 'https://url_da_cdn';
static GOOGLE_LOAD_BALANCE = 'nome_do_load_balance';
static DEFAULT_BUCKET = '';
static GOOGLE_URL_MAP_NAME = 'nome_da_url_map';
static CDN_TO_BUCKET = {
'url_do_cdn_1': [
'bucket_mapeado_1',
'bucket_mapeado_2'
],
'url_do_cdn_2': 'bucket_mapeado_1',
};
static initConfig() {
return {
cdn_key_name: 'nome_da_key_criado_no_load_balance',
cdn_key_value: 'valor_da_key_criado_no_load_balance',
google_key_file_path: 'arquivo_com_as_credenciais_do_gcp',
google_bucket_mapped: {
'url_do_cdn_1': [
'bucket_mapeado_1',
'bucket_mapeado_2'
],
'url_do_cdn_2': [
'bucket_mapeado_1'
]
},
cdn_hostname: new URL(this.VBN_PROD_URL).host,
google_key_json: 'arquivo_com_as_credenciais_do_gcp_em_formato_json',
};
}
## Opções de expiração da URL assinada
Duas camadas, independentes:
**1. Padrão global (no `init`)** — vale para toda assinatura sem opção explícita:
this.init({ ...this.initConfig(), default_use: 'web', // 'web' (padrão) | 'email' default_period: 'day', // 'day' (padrão) | 'weekly' | 'biweekly' | 'monthly' — só no modo web });
- `web`: a URL expira no **fim do período** (23:59:59 local + 1h de folga). Duas chamadas no mesmo
período geram a **mesma URL**, o que favorece o cache da CDN.
- `email`: a URL expira em `agora + TIME_URL_GCP` minutos (paridade com o client PHP).
Campos ausentes preservam o padrão `web`/`day`; valores inválidos caem no padrão.
**2. Por chamada (`ttlSeconds`)** — para link que sai da tela (e-mail, planilha exportada):
const single = VBNHelper.getOneFile('/bucket/pasta/laudo.pdf', { ttlSeconds: 30 * 86400 }); VBNHelper.getMultiplesFileSignature(paths, { ttlSeconds: 7 * 86400 });
- Expira em `agora + ttlSeconds`, ignorando `default_use`/`default_period`.
- Aceita inteiro de `1` a `VBNAutoAction.MAX_TTL_SECONDS` (30 dias). Fora disso a opção é
**ignorada** e vale o padrão — nunca lança.
- A URL **muda a cada chamada** (o `Expires` é relativo ao instante), então não serve para tela
com cache; para isso use o padrão global.
static async getOneSingleImage(bucketName, prefix) {
this.init(this.initConfig());
const imagePath = `/${bucketName}/${prefix}`;
const single = this.getOneFile(imagePath);
return single;
}
static async getImagesByPrefix(bucketName, prefix) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
if (!this._credentials) {
return [];
}
const [files] = await this._storage.bucket(bucketName).getFiles({ prefix });
const images = files.map(obj => `${bucketName}/${obj.name}`);
return this.getMultiplesImageSignature(images);
}
static async getMultiplesImage(images) {
this.init(this.initConfig());
return this.getMultiplesImageSignature(images);
}
static async invalidateVBNCache(imagePaths) {
this.init(this.initConfig());
return this.invalidateCache(imagePaths);
}
static async getSingleFileMetadata(imagePath, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
const cleanPath = VBNUtils.removeBucketFromUrl(imagePath, bucketName);
return this.getFileMetadata(cleanPath);
}
static async getMultiplesFileMetadata(imagePaths, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
let data = [];
for (const path of imagePaths) {
const cleanPath = VBNUtils.removeBucketFromUrl(path, bucketName);
const result = await this.getFileMetadata(cleanPath);
data = data.concat(result);
}
return data;
}
static async getFileMetadataByPrefix(imagePath, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
return this.getFileMetadata(imagePath, 'prefix');
}
async uploadFileByPath(file, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
delete file.base64;
return this.uploadFileInBucket(file);
}
async uploadFileByBase64(file, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
delete file.localPath;
return this.uploadFileInBucket(file);
}
async deleteSingleFile(filePath, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
return this.deleteFileInBucket(filePath, 'single');
}
async deleteFileByPrefix(filePrefix, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
return this.deleteFileInBucket(filePrefix, 'prefix');
}
async addSingleFileMetadata(filePath, bucketName) {
this.init(this.initConfig());
await VBNUtils.getGcpCredentials();
VBNUtils.setBucket(bucketName);
const single = {
fileName: filePath,
path: `${bucketName}/${filePath}`,
};
const metadata = {
[`${bucketName}/${filePath}`]: {
metadata1: 'metadados1',
segundometadados: 'outrometadados',
}
};
return this.addMetadataToSingle(single, metadata);
}
}
module.exports = VBNHelper;
