From 807319460425945731a81cb949866d562080249d Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 2 Dec 2025 15:10:31 -0300
Subject: [PATCH 01/41] fix: make Redis TLS configurable via REDIS_TLS env var
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Change TLS check from ENV !== 'local' to REDIS_TLS === 'true'
- Add REDIS_TLS env var to Helm deployment template
- Default to true for OCI Redis, can override for self-hosted K8s
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude
---
deploy/helm-chart/templates/deployment.yaml | 2 ++
deploy/helm-chart/values.yaml | 1 +
environment.d.ts | 1 +
src/services/service.module.ts | 2 +-
4 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/deploy/helm-chart/templates/deployment.yaml b/deploy/helm-chart/templates/deployment.yaml
index 013aa06..63524f3 100644
--- a/deploy/helm-chart/templates/deployment.yaml
+++ b/deploy/helm-chart/templates/deployment.yaml
@@ -104,6 +104,8 @@ spec:
value: {{ .Values.maestro.redis_host }}
- name: REDIS_PORT
value: "{{ .Values.maestro.redis_port }}"
+ - name: REDIS_TLS
+ value: "{{ .Values.maestro.redis_tls }}"
- name: JWT_PRIVATE_KEY
valueFrom:
secretKeyRef:
diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml
index 0c4db2e..2f703b7 100644
--- a/deploy/helm-chart/values.yaml
+++ b/deploy/helm-chart/values.yaml
@@ -48,6 +48,7 @@ maestro:
redis_host: "aaapzppmlyamkocqwstpo7zvopczyyiyuy6xzm2g6c5k4mq3a66be4a-0.redis.sa-saopaulo-1.oci.oraclecloud.com"
redis_port: "6379"
redis_database: "0"
+ redis_tls: "true"
cookie_secret: "13cc5e136d3074bcc05bec8697092ec1f5f376bf"
autoscaling:
enabled: false
diff --git a/environment.d.ts b/environment.d.ts
index 3b44250..85d1a52 100644
--- a/environment.d.ts
+++ b/environment.d.ts
@@ -16,6 +16,7 @@ declare global {
OPEN_CUSTOMER_ID: string;
DEDICATED_PROXY: string;
COOKIE_SECRET: string;
+ REDIS_TLS?: string;
}
}
}
diff --git a/src/services/service.module.ts b/src/services/service.module.ts
index 0286b01..8bf406d 100644
--- a/src/services/service.module.ts
+++ b/src/services/service.module.ts
@@ -14,7 +14,7 @@ import { redisStore } from 'cache-manager-ioredis-yet';
keyPrefix: 'maestro:sso',
}
- if (process.env.ENV !== 'local') {
+ if (process.env.REDIS_TLS === 'true') {
baseRedisConfig['tls'] = {
servername: process.env.REDIS_HOST,
}
From e789076ed4bfb581affa92e6725883c78b43d09e Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 2 Dec 2025 15:29:36 -0300
Subject: [PATCH 02/41] UPDATE: force deployment
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index bb50d3a..4d4a5b1 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
+
# Maestro
Maestro é a API principal da Dadosfera. É responsável pela comunicação do Frontend com nossos microsserviços.
From 7616b1e32c88fb40e9ec5731fd05d6b79a5d8c7c Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Wed, 3 Dec 2025 13:51:32 -0300
Subject: [PATCH 03/41] FEAT: add resource origin validate in me endpoint
---
src/modules/auth/auth.controller.ts | 125 ++++----------
src/modules/auth/auth.service.ts | 247 ++++++++++++++++++++++------
2 files changed, 226 insertions(+), 146 deletions(-)
diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts
index 9a4fb01..c648a41 100644
--- a/src/modules/auth/auth.controller.ts
+++ b/src/modules/auth/auth.controller.ts
@@ -13,6 +13,7 @@ import {
Req,
Param,
Res,
+ UnauthorizedException,
} from '@nestjs/common';
import {
ApiHeaders,
@@ -102,14 +103,13 @@ export class AuthController {
const data = await this.authClient.signIn({ username, password, totp }, metadata);
if (data.tokens) {
- this.addTokenInCookie(res, {
+ this.authClient.writeAuthSession(res, {
accessToken: data.tokens.accessToken,
refreshToken: data.tokens.refreshToken,
userId: data.user.id
});
}
-
return res.send(data);
} catch (error) {
this.logger.error('/auth - SignIn - ERROR', error);
@@ -126,27 +126,8 @@ export class AuthController {
) {
try {
this.logger.info('/auth - SignOut');
- const exp = 1000 * 60 * 3;
-
- res.cookie('ddf-auth', '', {
- domain: 'dadosfera.local',
- maxAge: Date.now() - exp,
- expires: new Date(),
- httpOnly: true,
- secure: true,
- sameSite: 'none', // Necessário para cookies em requisições cross-site
- });
-
- res.cookie('ddf-refresh-auth', '', {
- domain: 'dadosfera.local',
- maxAge: Date.now() - exp,
- expires: new Date(),
- httpOnly: true,
- secure: true,
- sameSite: 'none', // Necessário para cookies em requisições cross-site
- });
-
- this.logger.info('Clean cookie sessions');
+
+ this.authClient.cleanUpAuthSession(res);
return res.send();
} catch (error) {
@@ -175,8 +156,9 @@ export class AuthController {
const data = await this.authClient.refreshAccessToken({ refreshToken, userId }, metadata);
- this.addTokenInCookie(res, {
+ this.authClient.writeAuthSession(res, {
accessToken: data.accessToken,
+ refreshToken: data.refreshToken,
userId
});
@@ -492,85 +474,36 @@ export class AuthController {
@Get('me')
async getMe(@Req() req: Request, @Res() res: Response) {
this.logger.info('GET /auth/me ')
- // Lê cookies
+
+ // Get token and headers
const accessToken = req.cookies['ddf-auth'];
- const userId = req.cookies['ddf-user-id'];
+ const refreshToken = req.cookies['ddf-refresh-auth'];
+ const userId = req.cookies['ddf-user-id'];
+ const resourceOrigin = req.headers["origin"]
+
+ const hasUserSession = Boolean(accessToken) && Boolean(userId);
+ this.logger.info('Has User Session: ' + hasUserSession);
+
+ if (!hasUserSession) {
+ throw new UnauthorizedException()
+ }
- this.logger.info('Has cookie: ' + Boolean(accessToken))
try {
- // Decodifica e valida o JWT de acesso
- const userDto = await this.authClient.extractUserFrom(accessToken);
+ const userDto = await this.authClient.validateUserSession(accessToken, resourceOrigin);
return res.status(200).json(userDto);
- } catch (err) {
- this.logger.error(err.message);
- const refreshToken = req.cookies['ddf-refresh-auth'];
+ } catch (error) {
- this.logger.info('Token is invalid')
- this.logger.info('Has Refresh Token: '+ Boolean(refreshToken))
- // Se access token inválido, tenta refresh
- if (!refreshToken || !userId) {
+ if (!refreshToken) {
this.logger.error('Invalid refresh token or customer name');
- return res.status(401).json({ error: 'Not authenticated' });
- }
- try {
- // Chama refreshAccessToken
- const metadata = PackTheMetadata({
- });
- this.logger.info('Call Refresh Token')
- const data = await this.authClient.refreshAccessToken({ refreshToken, userId }, metadata);
- this.logger.info('Finish Refresh Token')
- // Retorna novo access token e dados mÃnimos
- this.addTokenInCookie(res, {
- accessToken: data.accessToken,
- userId
- });
- // Decodifica novo token
- const userDto = await this.authClient.extractUserFrom(accessToken);
- return res.status(200).json(userDto);
- } catch (refreshErr) {
- this.logger.error(refreshErr)
- return res.status(401).json({ error: 'Not authenticated' });
- }
- }
- }
+ throw new UnauthorizedException("Invalid refresh token or customer name");
+ };
- private addTokenInCookie(res: Response, data: CookiesValues) {
- let exp = 1000 * 60 * 5; // 5 minutes
-
- if (data.accessToken) {
- const { exp: expiration } = jwt.decode(data.accessToken) as JwtPayload;
- exp = (expiration - 30) * 1000; // exp em segundos, maxAge em ms
-
- this.logger.info('Set Cookie ddf-auth')
- res.cookie('ddf-auth', data.accessToken, {
- domain: '.dadosfera.ai',
- maxAge: exp,
- httpOnly: true,
- secure: true,
- sameSite: 'none', // Necessário para cookies em requisições cross-site
- });
- }
-
- if (data.refreshToken) {
- this.logger.info('Set Cookie ddf-refresh-auth')
- res.cookie('ddf-refresh-auth', data.refreshToken, {
- domain: '.dadosfera.ai',
- maxAge: exp,
- httpOnly: true,
- secure: true,
- sameSite: 'none', // Necessário para cookies em requisições cross-site
- });
- }
-
- if (data.userId) {
- this.logger.info('Set Cookie ddf-refresh-auth')
- res.cookie('ddf-user-id', data.userId, {
- domain: '.dadosfera.ai',
- maxAge: exp,
- httpOnly: true,
- secure: true,
- sameSite: 'none', // Necessário para cookies em requisições cross-site
- });
+ const {
+ authSession,
+ user
+ } = await this.authClient.refreshUserSession(refreshToken, userId, resourceOrigin);
+ this.authClient.writeAuthSession(res, authSession);
+ return res.status(200).json(user);
}
}
}
diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts
index 3a17327..3133462 100644
--- a/src/modules/auth/auth.service.ts
+++ b/src/modules/auth/auth.service.ts
@@ -1,10 +1,20 @@
-import { OnModuleInit, Inject, Injectable, ForbiddenException } from '@nestjs/common';
+import {
+ OnModuleInit,
+ Inject,
+ Injectable,
+ ForbiddenException,
+ UnauthorizedException,
+} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { lastValueFrom } from 'rxjs';
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
-import { AuthProtoService as AuthServiceInterface, IdentityProviderProtoService, UsersProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
+import {
+ AuthProtoService as AuthServiceInterface,
+ IdentityProviderProtoService,
+ UsersProtoService,
+} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
import {
AuthSnowflakeSignInRequest,
AuthSignInRequest,
@@ -22,12 +32,18 @@ import {
import { DucClient } from '../duc/client.config';
import { Metadata } from '@grpc/grpc-js';
import { BulkEditResponse, UserDTO } from './dtos/login';
-import jwt from 'jsonwebtoken';
+import jwt, { JwtPayload } from 'jsonwebtoken';
import { PackTheMetadata } from 'src/utils/PackTheMetadata';
+import { Request, Response } from 'express';
+
+type AuthSession = {
+ accessToken?: string;
+ refreshToken?: string;
+ userId?: string;
+};
@Injectable()
export class AuthClientService implements OnModuleInit {
-
logger: DadosferaLogger;
private authService: AuthServiceInterface;
@@ -63,11 +79,11 @@ export class AuthClientService implements OnModuleInit {
return lastValueFrom(this.authService.AuthSnowflakeSignIn(input));
}
- checkDedicatedProxy({
- customer
- }: AuthSignInResponse) {
+ checkDedicatedProxy({ customer }: AuthSignInResponse) {
const DEDICATED_PROXY = process.env.DEDICATED_PROXY || '';
- this.logger.info('SignIn - Setting customer ID for dedicated proxy: ' + DEDICATED_PROXY);
+ this.logger.info(
+ 'SignIn - Setting customer ID for dedicated proxy: ' + DEDICATED_PROXY,
+ );
this.logger.info('Customer ID: ' + customer.id);
if (DEDICATED_PROXY !== '' && DEDICATED_PROXY !== customer.id) {
@@ -75,7 +91,9 @@ export class AuthClientService implements OnModuleInit {
}
// Bloquear o customer de acesso o maestro publico
- this.logger.info('Check if customer have network policy: ' + customer.modules);
+ this.logger.info(
+ 'Check if customer have network policy: ' + customer.modules,
+ );
const hasNetworkPolicyModule = customer.modules.includes('network-policy');
if (hasNetworkPolicyModule && DEDICATED_PROXY === '') {
throw new ForbiddenException();
@@ -94,7 +112,6 @@ export class AuthClientService implements OnModuleInit {
result = await lastValueFrom(
this.authService.AuthSignIn({ username, password, totp }, metadata),
);
-
} catch (error) {
this.logger.error('SignIn - Error during sign-in');
this.logger.error(error);
@@ -105,7 +122,7 @@ export class AuthClientService implements OnModuleInit {
this.checkDedicatedProxy(result);
}
- return result
+ return result;
}
async refreshAccessToken(
@@ -115,7 +132,10 @@ export class AuthClientService implements OnModuleInit {
this.logger.info('RefreshAccessToken');
return lastValueFrom(
- this.authService.AuthRefreshAccessToken({ refreshToken, userId }, metadata),
+ this.authService.AuthRefreshAccessToken(
+ { refreshToken, userId },
+ metadata,
+ ),
);
}
@@ -284,50 +304,177 @@ export class AuthClientService implements OnModuleInit {
}
}
- private async getUser(id: string, metadata: Metadata) {
- this.logger.info('getUser');
- return await lastValueFrom(
- this.userService.UserFindOneById({ id }, metadata),
- );
+ public async validateUserSession(accessToken: any, originHeader: string) {
+ const payload = await this.validateJwtToken(accessToken);
+
+ const userDto = await this.getUserfromPayload(payload);
+
+ this.validateResourceAccess(originHeader, userDto);
+ return userDto;
}
- public async extractUserFrom(token: string) {
- const decoded: any = token && jwt.decode(token, { complete: true });
- if (!decoded) throw new Error('Invalid token');
+ public async refreshUserSession(
+ refreshToken: string,
+ userId: string,
+ originHeader: string,
+ ): Promise<{
+ user: UserDTO;
+ authSession: AuthSession;
+ }> {
+ const metadata = PackTheMetadata({});
- const { kid } = decoded.header;
- // Busca a chave pública
- const { keys } = await this.getPublicKeys();
- const pemValue = keys.find((k) => k.kid === kid)?.pem;
- if (!pemValue)
- throw new Error('Public key not found');
- jwt.verify(token, pemValue);
+ this.logger.info('Call Refresh Token');
+ const refreshCredentials = await this.refreshAccessToken(
+ { refreshToken, userId },
+ metadata,
+ );
+ this.logger.info('Finish Refresh Token');
- const payload = decoded.payload;
- const metadata = PackTheMetadata({
- customer_id: payload.customer_id
- })
+ const userDto = await this.validateUserSession(
+ refreshCredentials.accessToken,
+ originHeader,
+ );
+ return {
+ user: userDto,
+ authSession: {
+ accessToken: refreshCredentials.accessToken,
+ refreshToken: refreshCredentials.refreshToken,
+ userId,
+ },
+ };
+ }
- const {
- user
- } = await this.getUser(
- payload.user_id,
- metadata
- );
+ public writeAuthSession(res: Response, data: AuthSession) {
+ let exp = 1000 * 60 * 5; // 5 minutes
- const userDto: UserDTO = {
- id: user.id,
- name: user.username,
- jobTitle: user?.jobTitle || null,
- department: user?.department || null,
- hierarchy: user?.hierarchy || null,
- customer: {
- id: payload.customer_id,
- name: payload.customer_name,
- tier: payload.customer_tier,
- }
- };
+ if (data.accessToken) {
+ const { exp: expiration } = jwt.decode(data.accessToken) as JwtPayload;
+ exp = (expiration - 30) * 1000; // exp em segundos, maxAge em ms
- return userDto;
+ this.logger.info('Set Cookie ddf-auth');
+ res.cookie('ddf-auth', data.accessToken, {
+ domain: '.dadosfera.ai',
+ maxAge: exp,
+ httpOnly: true,
+ secure: true,
+ sameSite: 'none', // Necessário para cookies em requisições cross-site
+ });
}
+
+ if (data.refreshToken) {
+ this.logger.info('Set Cookie ddf-refresh-auth');
+ res.cookie('ddf-refresh-auth', data.refreshToken, {
+ domain: '.dadosfera.ai',
+ maxAge: exp,
+ httpOnly: true,
+ secure: true,
+ sameSite: 'none', // Necessário para cookies em requisições cross-site
+ });
+ }
+
+ if (data.userId) {
+ this.logger.info('Set Cookie ddf-refresh-auth');
+ res.cookie('ddf-user-id', data.userId, {
+ domain: '.dadosfera.ai',
+ maxAge: exp,
+ httpOnly: true,
+ secure: true,
+ sameSite: 'none', // Necessário para cookies em requisições cross-site
+ });
+ }
+ }
+
+ public cleanUpAuthSession(res: Response) {
+ const exp = 1000 * 60 * 3;
+
+ res.cookie('ddf-auth', '', {
+ domain: 'dadosfera.ai',
+ maxAge: Date.now() - exp,
+ expires: new Date(),
+ httpOnly: true,
+ secure: true,
+ sameSite: 'none', // Necessário para cookies em requisições cross-site
+ });
+
+ res.cookie('ddf-refresh-auth', '', {
+ domain: 'dadosfera.ai',
+ maxAge: Date.now() - exp,
+ expires: new Date(),
+ httpOnly: true,
+ secure: true,
+ sameSite: 'none', // Necessário para cookies em requisições cross-site
+ });
+
+ this.logger.info('Clean cookie sessions');
+ }
+
+ private async validateJwtToken(token: string) {
+ const decoded: any = token && jwt.decode(token, { complete: true });
+ if (!decoded) throw new Error('Invalid token');
+
+ const { kid } = decoded.header;
+ // Busca a chave pública
+ const { keys } = await this.getPublicKeys();
+ const pemValue = keys.find((k) => k.kid === kid)?.pem;
+ if (!pemValue) throw new Error('Public key not found');
+ jwt.verify(token, pemValue);
+
+ return decoded.payload;
+ }
+
+ private async getUserfromPayload(payload: JwtPayload): Promise {
+ this.logger.info('getUser');
+
+ const metadata = PackTheMetadata({
+ customer_id: payload.customer_id,
+ });
+
+ const { user } = await lastValueFrom(
+ this.userService.UserFindOneById({ id: payload.user_id }, metadata),
+ );
+
+ const userDto: UserDTO = {
+ id: user.id,
+ name: user.username,
+ jobTitle: user?.jobTitle || null,
+ department: user?.department || null,
+ hierarchy: user?.hierarchy || null,
+ customer: {
+ id: payload.customer_id,
+ name: payload.customer_name,
+ tier: payload.customer_tier,
+ },
+ };
+
+ return userDto;
+ }
+
+ private validateResourceAccess(origin: string, user: UserDTO) {
+ this.logger.info(
+ "Validate whether the source URL is a resource belonging to the user's client",
+ );
+ this.logger.info('Origin: ' + origin);
+ this.logger.info('Customer: ' + user.customer.name);
+
+ const urlParts = origin.replace('https://', '').split('.');
+ const domain = urlParts[0];
+ const isResouceStg = urlParts[1] === 'stg';
+
+ const domainParts = domain.split('-');
+ const customerInDomain = domainParts[domainParts.length - 1];
+
+ if (isResouceStg && process.env.ENV !== 'stg') {
+ throw new ForbiddenException(
+ `Customer ${user.customer.name} cannot access ${origin}`,
+ );
+ }
+
+ if (customerInDomain != user.customer.name) {
+ throw new ForbiddenException(
+ `Customer ${user.customer.name} cannot access ${origin}`,
+ );
+ }
+
+ return;
+ }
}
From 82290285d015bdacfeaa01614937e8f7abbb63f0 Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Wed, 3 Dec 2025 14:41:51 -0300
Subject: [PATCH 04/41] FIX: using header host
---
src/modules/auth/auth.controller.ts | 6 +++---
src/modules/auth/auth.service.ts | 10 +++++-----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts
index c648a41..3d86f14 100644
--- a/src/modules/auth/auth.controller.ts
+++ b/src/modules/auth/auth.controller.ts
@@ -479,7 +479,7 @@ export class AuthController {
const accessToken = req.cookies['ddf-auth'];
const refreshToken = req.cookies['ddf-refresh-auth'];
const userId = req.cookies['ddf-user-id'];
- const resourceOrigin = req.headers["origin"]
+ const resourceHost = req.headers["host"]
const hasUserSession = Boolean(accessToken) && Boolean(userId);
this.logger.info('Has User Session: ' + hasUserSession);
@@ -489,7 +489,7 @@ export class AuthController {
}
try {
- const userDto = await this.authClient.validateUserSession(accessToken, resourceOrigin);
+ const userDto = await this.authClient.validateUserSession(accessToken, resourceHost);
return res.status(200).json(userDto);
} catch (error) {
@@ -501,7 +501,7 @@ export class AuthController {
const {
authSession,
user
- } = await this.authClient.refreshUserSession(refreshToken, userId, resourceOrigin);
+ } = await this.authClient.refreshUserSession(refreshToken, userId, resourceHost);
this.authClient.writeAuthSession(res, authSession);
return res.status(200).json(user);
}
diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts
index 3133462..3229752 100644
--- a/src/modules/auth/auth.service.ts
+++ b/src/modules/auth/auth.service.ts
@@ -449,16 +449,16 @@ export class AuthClientService implements OnModuleInit {
return userDto;
}
- private validateResourceAccess(origin: string, user: UserDTO) {
+ private validateResourceAccess(host: string, user: UserDTO) {
this.logger.info(
"Validate whether the source URL is a resource belonging to the user's client",
);
- this.logger.info('Origin: ' + origin);
+ this.logger.info('Host: ' + host);
this.logger.info('Customer: ' + user.customer.name);
- const urlParts = origin.replace('https://', '').split('.');
- const domain = urlParts[0];
- const isResouceStg = urlParts[1] === 'stg';
+ const hostParts = host.split('.');
+ const domain = hostParts[0];
+ const isResouceStg = hostParts[1] === 'stg';
const domainParts = domain.split('-');
const customerInDomain = domainParts[domainParts.length - 1];
From bb671a90d61310cbc35e765c637ee0cec04ee1e1 Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Wed, 3 Dec 2025 15:20:41 -0300
Subject: [PATCH 05/41] FIX: change origin to host
---
src/modules/auth/auth.service.ts | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts
index 3229752..c1b85f6 100644
--- a/src/modules/auth/auth.service.ts
+++ b/src/modules/auth/auth.service.ts
@@ -3,7 +3,8 @@ import {
Inject,
Injectable,
ForbiddenException,
- UnauthorizedException,
+ HttpException,
+ HttpStatus,
} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
@@ -12,7 +13,6 @@ import { lastValueFrom } from 'rxjs';
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
import {
AuthProtoService as AuthServiceInterface,
- IdentityProviderProtoService,
UsersProtoService,
} from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
import {
@@ -304,12 +304,12 @@ export class AuthClientService implements OnModuleInit {
}
}
- public async validateUserSession(accessToken: any, originHeader: string) {
+ public async validateUserSession(accessToken: any, resourceHost: string) {
const payload = await this.validateJwtToken(accessToken);
const userDto = await this.getUserfromPayload(payload);
- this.validateResourceAccess(originHeader, userDto);
+ this.validateResourceAccess(resourceHost, userDto);
return userDto;
}
@@ -460,18 +460,30 @@ export class AuthClientService implements OnModuleInit {
const domain = hostParts[0];
const isResouceStg = hostParts[1] === 'stg';
+ const notFoundCustomerInDomain = !domain.includes('-')
+
+ if (notFoundCustomerInDomain) {
+ this.logger.info(`Not found Customer Name in domain`);
+ return;
+ }
+
const domainParts = domain.split('-');
+
const customerInDomain = domainParts[domainParts.length - 1];
if (isResouceStg && process.env.ENV !== 'stg') {
- throw new ForbiddenException(
- `Customer ${user.customer.name} cannot access ${origin}`,
+ this.logger.error(`Customer ${user.customer.name} cannot access ${host}`);
+ throw new HttpException(
+ `Customer ${user.customer.name} cannot access ${host}`,
+ HttpStatus.FORBIDDEN
);
}
if (customerInDomain != user.customer.name) {
- throw new ForbiddenException(
- `Customer ${user.customer.name} cannot access ${origin}`,
+ this.logger.error(`Customer ${user.customer.name} cannot access ${host}`);
+ throw new HttpException(
+ `Customer ${user.customer.name} cannot access ${host}`,
+ HttpStatus.FORBIDDEN
);
}
From 399d3492d38ccb34ba5aaa93be2f0aa3a4180861 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Tue, 9 Dec 2025 14:46:02 -0300
Subject: [PATCH 06/41] DOCS: update @dadosfera/protospack-v2 to version
3.38.0-beta.15
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index e58ffab..8c9f50b 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"@aws-sdk/client-secrets-manager": "^3.414.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.14",
+ "@dadosfera/protospack-v2": "3.38.0-beta.15",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
From c21d977f7c6fba15a502465dee1517fbb725e895 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Tue, 9 Dec 2025 14:51:25 -0300
Subject: [PATCH 07/41] FEAT: enhance catalog service to support any asset type
in data docs creation
---
src/modules/catalog/catalog.controller.ts | 27 +++++++++++---
src/modules/catalog/catalog.service.ts | 45 ++++++++++++++++++-----
src/modules/catalog/dtos/index.ts | 7 ++++
3 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/src/modules/catalog/catalog.controller.ts b/src/modules/catalog/catalog.controller.ts
index b87829b..13bcf42 100644
--- a/src/modules/catalog/catalog.controller.ts
+++ b/src/modules/catalog/catalog.controller.ts
@@ -439,7 +439,13 @@ export class CatalogController {
language,
});
- const docs = await this.catalogService.getDataDocs(id, metadata);
+ const { data_asset } = await this.catalogService.getOneDataAsset({
+ customer_id,
+ id,
+ metadata,
+ });
+
+ const docs = await this.catalogService.getDataDocs(id, data_asset.data_asset_type, metadata);
return { docs };
}
@@ -487,21 +493,32 @@ export class CatalogController {
@Headers() headers,
@Param('id') table_id: string,
@Body('docs') docs: string,
+ @Query('asset_type') asset_type: string,
) {
- const { user_id, customer_name } = user;
+ const { user_id, customer_name, customer_id, username } = user;
+
+ const metadata = PackTheMetadata({
+ customer_id,
+ customer_name,
+ user_id,
+ username,
+ });
- this.logger.info(`/catalog - ON GET DATA DOCS ROUTE`, {
+ this.logger.info(`/catalog - ON POST DATA DOCS ROUTE`, {
user_id,
customer_name,
});
- const res = await this.catalogService.createDataDocs({
+ const body = {
table_id,
docs,
+ asset_type,
info: {
customer: customer_name,
},
- });
+ }
+
+ const res = await this.catalogService.createDataDocs(body, metadata);
return res;
}
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 1848dcd..16cc4ab 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -24,9 +24,11 @@ import { CatalogClientConfiguration } from './catalog-client';
import { UsersService } from '../users/users.service';
import { RolesService } from '../roles/roles.service';
import { Metadata } from '@grpc/grpc-js';
+import { PackTheMetadata } from 'src/utils/PackTheMetadata';
import {
AssetReporter,
BatchRemoveRlsRulesRequest,
+ CreateDataDocsDTO,
IUpdateDataRequest,
TriggerCatalogReq,
} from './dtos';
@@ -337,9 +339,11 @@ class CatalogService implements OnModuleInit {
return { data_asset: asset[0] };
}
- async getDataDocs(id: string, metadata: Metadata) {
+ async getDataDocs(id: string, assetType: string, metadata: Metadata) {
+ const requestType = assetType === 'dataset' ? undefined : assetType;
+
const { documentation } = await lastValueFrom(
- this.catalogReadService.GetDatasetDoc({ id, type: undefined }, metadata),
+ this.catalogReadService.GetDatasetDoc({ id, type: requestType }, metadata),
);
const docs = JSON.parse(documentation);
@@ -368,13 +372,36 @@ class CatalogService implements OnModuleInit {
return result;
}
- async createDataDocs(body) {
- const nimbusUrl = this._getNimbusUrl(body);
- const { data } = await axios.post(
- `${nimbusUrl}/api/catalog/data-docs/`,
- body,
- );
- return data;
+ async createDataDocs(body: CreateDataDocsDTO, metadata: Metadata) {
+ if (body.asset_type === 'table' || body.asset_type === 'view') {
+ const nimbusUrl = this._getNimbusUrl(body);
+ const { data } = await axios.post(
+ `${nimbusUrl}/api/catalog/data-docs/`,
+ body,
+ );
+ return data;
+ }
+
+ try {
+ const response: any = await lastValueFrom(
+ this.catalogWriteService.UpdateDataAssetDoc(
+ {
+ id: body.table_id,
+ docs: body.docs,
+ },
+ metadata,
+ ),
+ );
+
+ return response;
+
+ } catch (error) {
+ this.logger.error('Error creating data asset docs:', error);
+ throw new HttpException(
+ 'Failed to create data asset documentation',
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ );
+ }
}
async findAllTags(data, metadata) {
diff --git a/src/modules/catalog/dtos/index.ts b/src/modules/catalog/dtos/index.ts
index ef12e78..4989672 100644
--- a/src/modules/catalog/dtos/index.ts
+++ b/src/modules/catalog/dtos/index.ts
@@ -328,3 +328,10 @@ export type AssetReporter = {
created_at: string;
tags: string;
}
+
+export type CreateDataDocsDTO = {
+ table_id: string;
+ docs: string;
+ asset_type: string;
+
+}
\ No newline at end of file
From a0a1303515fedee6c81eb5a5e1a525d43f5c6aad Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Tue, 9 Dec 2025 14:54:39 -0300
Subject: [PATCH 08/41] DOCS: add automatic asset_type query parameter to API
schema and packages dependencies
---
docsfera.json | 8 +++++
package-lock.json | 76 +++++++++++++++++++++--------------------------
2 files changed, 42 insertions(+), 42 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index ab3a2c1..591cea9 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -4471,6 +4471,14 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "asset_type",
+ "required": true,
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
diff --git a/package-lock.json b/package-lock.json
index 0a1aa0e..2764511 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"@aws-sdk/client-secrets-manager": "^3.414.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.14",
+ "@dadosfera/protospack-v2": "3.38.0-beta.15",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
@@ -850,7 +850,6 @@
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.2",
@@ -1409,10 +1408,9 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
- "version": "3.38.0-beta.14",
- "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.14.tgz",
- "integrity": "sha512-BiE1fUIHuam3cJjAGIknsRNIlf1Z0JHJOV/VZ2pyAp5mIkGOSoNFBAMXJZb+VMTnd2xsp+vPxNnWVu7OJ/CvMQ==",
- "license": "ISC",
+ "version": "3.38.0-beta.15",
+ "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.15.tgz",
+ "integrity": "sha512-WJ6wANzTt/fo0BrE7nviAqwN1COh66qIujoYfBlHW7FgrHkgu8CAUF38WmtjqjYCvpfcd/A1j1MESsuUg9QWJw==",
"dependencies": {
"@grpc/grpc-js": "^1.9.3",
"rxjs": "^7.5.5"
@@ -2261,7 +2259,6 @@
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.4.3.tgz",
"integrity": "sha512-Gd6D4IaYj01o14Bwv81ukidn4w3bPHCblMUq+SmUmWLyosK+XQmInCS09SbDDZyL8jy86PngtBLTdhJ2bXSUig==",
"license": "MIT",
- "peer": true,
"dependencies": {
"iterare": "1.2.1",
"tslib": "2.5.3",
@@ -2340,7 +2337,6 @@
"integrity": "sha512-Qi63+wi55Jh4sDyaj5Hhx2jOpKqT386aeo+VOKsxnd+Ql9VvkO/FjmuwBGUyzkJt29ENYc+P0Sx/k5LtstNpPQ==",
"hasInstallScript": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@nuxtjs/opencollective": "0.3.2",
"fast-safe-stringify": "2.1.1",
@@ -2478,7 +2474,6 @@
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.4.3.tgz",
"integrity": "sha512-FpdczWoRSC0zz2dNL9u2AQLXKXRVtq4HgHklAhbL59X0uy+mcxhlSThG7DHzDMkoSnuuHY8ojDVf7mDxk+GtCw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"body-parser": "1.20.2",
"cors": "2.8.5",
@@ -2842,7 +2837,6 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"license": "Apache-2.0",
- "peer": true,
"engines": {
"node": ">=8.0.0"
}
@@ -3002,7 +2996,6 @@
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
"integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"cluster-key-slot": "1.1.2",
"generic-pool": "3.9.0",
@@ -3799,7 +3792,6 @@
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
@@ -3880,7 +3872,6 @@
"integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"jest-diff": "^27.0.0",
"pretty-format": "^27.0.0"
@@ -3944,8 +3935,7 @@
"version": "16.18.126",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
"integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/@types/oauth": {
"version": "0.9.6",
@@ -4175,7 +4165,6 @@
"integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.62.0",
"@typescript-eslint/types": "5.62.0",
@@ -4522,7 +4511,6 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4619,7 +4607,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -5248,7 +5235,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -5355,7 +5341,6 @@
"resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz",
"integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==",
"license": "MIT",
- "peer": true,
"dependencies": {
"eventemitter3": "^5.0.1",
"lodash.clonedeep": "^4.5.0",
@@ -5579,15 +5564,13 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/class-validator": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
"integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/validator": "^13.11.8",
"libphonenumber-js": "^1.10.53",
@@ -6251,8 +6234,7 @@
"version": "0.0.1425554",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1425554.tgz",
"integrity": "sha512-uRfxR6Nlzdzt0ihVIkV+sLztKgs7rgquY/Mhcv1YNCWDh5IZgl5mnn2aeEnW5stYTE0wwiF4RYVz8eMEpV1SEw==",
- "license": "BSD-3-Clause",
- "peer": true
+ "license": "BSD-3-Clause"
},
"node_modules/dezalgo": {
"version": "1.0.4",
@@ -6529,6 +6511,7 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">= 0.8"
}
@@ -6716,7 +6699,6 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -7063,6 +7045,7 @@
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -7109,6 +7092,7 @@
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -7133,6 +7117,7 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">= 0.6"
}
@@ -7142,6 +7127,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -7150,19 +7136,22 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/express/node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/express/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
+ "peer": true,
"dependencies": {
"side-channel": "^1.0.6"
},
@@ -7191,7 +7180,8 @@
"url": "https://feross.org/support"
}
],
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/external-editor": {
"version": "3.1.0",
@@ -7426,6 +7416,7 @@
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
@@ -7444,6 +7435,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -7452,7 +7444,8 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/find-up": {
"version": "5.0.0",
@@ -8246,7 +8239,6 @@
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
@@ -8588,7 +8580,6 @@
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@jest/core": "^27.5.1",
"import-local": "^3.0.2",
@@ -9878,6 +9869,7 @@
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
+ "peer": true,
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@@ -10635,7 +10627,6 @@
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
"license": "MIT",
- "peer": true,
"dependencies": {
"passport-strategy": "1.x.x",
"pause": "0.0.1",
@@ -11025,7 +11016,6 @@
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"prettier": "bin-prettier.js"
},
@@ -11528,8 +11518,7 @@
"version": "0.1.14",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz",
"integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==",
- "license": "Apache-2.0",
- "peer": true
+ "license": "Apache-2.0"
},
"node_modules/relative-microtime": {
"version": "2.0.0",
@@ -11716,7 +11705,6 @@
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"license": "Apache-2.0",
- "peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
@@ -11778,7 +11766,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -11822,6 +11809,7 @@
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -11846,6 +11834,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -11854,13 +11843,15 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">= 0.8"
}
@@ -11869,7 +11860,8 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
@@ -11885,6 +11877,7 @@
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
@@ -12862,7 +12855,6 @@
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -13092,7 +13084,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -13420,6 +13411,7 @@
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
From b1dc5673942a900736cf061b2367cf6f8846bdb3 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Wed, 10 Dec 2025 11:12:13 -0300
Subject: [PATCH 09/41] DOCS: update @dadosfera/protospack-v2 to version
3.38.0-beta.16
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 2764511..5d30872 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"@aws-sdk/client-secrets-manager": "^3.414.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.15",
+ "@dadosfera/protospack-v2": "3.38.0-beta.16",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
@@ -1408,9 +1408,9 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
- "version": "3.38.0-beta.15",
- "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.15.tgz",
- "integrity": "sha512-WJ6wANzTt/fo0BrE7nviAqwN1COh66qIujoYfBlHW7FgrHkgu8CAUF38WmtjqjYCvpfcd/A1j1MESsuUg9QWJw==",
+ "version": "3.38.0-beta.16",
+ "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.16.tgz",
+ "integrity": "sha512-ijURcmETXdgVgXhIPxapK7w0z6begXm4WDZ6EJtUGg+oYlJd9QOxbwaD7akRzW8XTdccmIo0Vov065KB812J0A==",
"dependencies": {
"@grpc/grpc-js": "^1.9.3",
"rxjs": "^7.5.5"
diff --git a/package.json b/package.json
index 8c9f50b..1da6c28 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"@aws-sdk/client-secrets-manager": "^3.414.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.15",
+ "@dadosfera/protospack-v2": "3.38.0-beta.16",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
From 165b533172502ba2bf35a778581b98fb52cc8bec Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Wed, 10 Dec 2025 11:17:43 -0300
Subject: [PATCH 10/41] FIX: removing unnecessary type parameter from
GetDatasetDoc call
---
src/modules/catalog/share/share.service.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/catalog/share/share.service.ts b/src/modules/catalog/share/share.service.ts
index 3e088a6..86b17b9 100644
--- a/src/modules/catalog/share/share.service.ts
+++ b/src/modules/catalog/share/share.service.ts
@@ -160,7 +160,7 @@ export class ShareService implements OnModuleInit {
});
const { documentation } = await lastValueFrom(
- this.catalogReadService.GetDatasetDoc({ id, type: undefined }, metadata),
+ this.catalogReadService.GetDatasetDoc({ id }, metadata),
);
console.log(documentation);
const docs = JSON.parse(documentation);
From 09dced9fcdec7da65342f703b736cf571df7ee0b Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Wed, 10 Dec 2025 11:21:46 -0300
Subject: [PATCH 11/41] REFACTOR: add asset_type query parameter to getDataDocs
and separate data docs methods
---
src/modules/catalog/catalog.controller.ts | 9 ++------
src/modules/catalog/catalog.service.ts | 28 +++++++++++++++--------
2 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/src/modules/catalog/catalog.controller.ts b/src/modules/catalog/catalog.controller.ts
index 13bcf42..83c1386 100644
--- a/src/modules/catalog/catalog.controller.ts
+++ b/src/modules/catalog/catalog.controller.ts
@@ -423,6 +423,7 @@ export class CatalogController {
@User() user: RequestUser,
@Language() language: LanguageEnum,
@Param('id') id: string,
+ @Query('asset_type') asset_type: string,
): Promise {
const { customer_name, customer_id, user_id, username } = user;
@@ -439,13 +440,7 @@ export class CatalogController {
language,
});
- const { data_asset } = await this.catalogService.getOneDataAsset({
- customer_id,
- id,
- metadata,
- });
-
- const docs = await this.catalogService.getDataDocs(id, data_asset.data_asset_type, metadata);
+ const docs = await this.catalogService.getDataDocs(id, asset_type, metadata);
return { docs };
}
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 16cc4ab..73c9111 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -340,10 +340,8 @@ class CatalogService implements OnModuleInit {
}
async getDataDocs(id: string, assetType: string, metadata: Metadata) {
- const requestType = assetType === 'dataset' ? undefined : assetType;
-
const { documentation } = await lastValueFrom(
- this.catalogReadService.GetDatasetDoc({ id, type: requestType }, metadata),
+ this.catalogReadService.GetDatasetDoc({ id }, metadata),
);
const docs = JSON.parse(documentation);
@@ -374,14 +372,24 @@ class CatalogService implements OnModuleInit {
async createDataDocs(body: CreateDataDocsDTO, metadata: Metadata) {
if (body.asset_type === 'table' || body.asset_type === 'view') {
- const nimbusUrl = this._getNimbusUrl(body);
- const { data } = await axios.post(
- `${nimbusUrl}/api/catalog/data-docs/`,
- body,
- );
- return data;
+ return this.createDataDocsViaNimbus(body);
}
-
+
+ return this.createDataDocsViaGrpc(body, metadata);
+ }
+
+ private async createDataDocsViaNimbus(body: CreateDataDocsDTO) {
+ this.logger.info('Creating data docs via Nimbus for table/view');
+ const nimbusUrl = this._getNimbusUrl(body);
+ const { data } = await axios.post(
+ `${nimbusUrl}/api/catalog/data-docs/`,
+ body,
+ );
+ return data;
+ }
+
+ private async createDataDocsViaGrpc(body: CreateDataDocsDTO, metadata: Metadata) {
+ this.logger.info('Creating data docs via gRPC for other asset types');
try {
const response: any = await lastValueFrom(
this.catalogWriteService.UpdateDataAssetDoc(
From df674dd441ca8ce8be4a940929756c0c12cbda54 Mon Sep 17 00:00:00 2001
From: Rafael
Date: Wed, 10 Dec 2025 12:41:14 -0300
Subject: [PATCH 12/41] FEAT: add Platform API proxy with Elasticsearch and
DynamoDB sync
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add Platform API module to proxy requests to Platform API service
- Add Elasticsearch service for pipeline catalog sync (CRUD operations)
- Add DynamoDB service for storing pipeline tables/inputs configuration
- Sync pipeline creation/update/delete to Elasticsearch index
- Extract tables from jobs with connector-specific mappings:
- JDBC: table_name, load_type, column_include_list, incremental_column_name
- Singer: replication_method -> full_load/incremental
- S3: same as Singer
- Map connector types to DynamoDB types (jdbc->database, singer->application, s3->file)
- Validate connector type is provided in job input
- Normalize pipeline IDs for Platform API (replace - with _), keep UUIDs for ES
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
package-lock.json | 2194 ++++++++++++++---
package.json | 7 +-
src/app.module.ts | 2 +
.../platform-api/platform-api.config.ts | 11 +
.../platform-api/platform-api.controller.ts | 663 +++++
.../platform-api/platform-api.module.ts | 16 +
.../platform-api/platform-api.service.ts | 123 +
src/services/dynamodb/dynamodb.config.ts | 4 +
src/services/dynamodb/dynamodb.module.ts | 9 +
src/services/dynamodb/dynamodb.service.ts | 148 ++
src/services/dynamodb/index.ts | 3 +
.../elasticsearch/elasticsearch.config.ts | 5 +
.../elasticsearch/elasticsearch.module.ts | 9 +
.../elasticsearch/elasticsearch.service.ts | 375 +++
src/services/elasticsearch/index.ts | 3 +
15 files changed, 3277 insertions(+), 295 deletions(-)
create mode 100644 src/modules/platform-api/platform-api.config.ts
create mode 100644 src/modules/platform-api/platform-api.controller.ts
create mode 100644 src/modules/platform-api/platform-api.module.ts
create mode 100644 src/modules/platform-api/platform-api.service.ts
create mode 100644 src/services/dynamodb/dynamodb.config.ts
create mode 100644 src/services/dynamodb/dynamodb.module.ts
create mode 100644 src/services/dynamodb/dynamodb.service.ts
create mode 100644 src/services/dynamodb/index.ts
create mode 100644 src/services/elasticsearch/elasticsearch.config.ts
create mode 100644 src/services/elasticsearch/elasticsearch.module.ts
create mode 100644 src/services/elasticsearch/elasticsearch.service.ts
create mode 100644 src/services/elasticsearch/index.ts
diff --git a/package-lock.json b/package-lock.json
index b491a76..35fb021 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,12 @@
"version": "0.0.0",
"license": "UNLICENSED",
"dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-sdk/client-dynamodb": "^3.414.0",
"@aws-sdk/client-secrets-manager": "^3.414.0",
+ "@aws-sdk/credential-provider-node": "^3.940.0",
+ "@aws-sdk/lib-dynamodb": "^3.414.0",
+ "@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
"@dadosfera/protospack-v2": "3.38.0-beta.10",
@@ -57,8 +62,8 @@
"swagger-ui-express": "^4.6.3"
},
"devDependencies": {
- "@types/cookie-parser": "^1.4.9",
"@types/cache-manager": "^4.0.6",
+ "@types/cookie-parser": "^1.4.9",
"@types/express": "^4.17.17",
"@types/express-session": "^1.18.1",
"@types/jest": "27.0.2",
@@ -214,6 +219,34 @@
"tslib": "^2.1.0"
}
},
+ "node_modules/@aws-crypto/crc32": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz",
+ "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32/node_modules/@aws-crypto/util": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
+ "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "license": "0BSD"
+ },
"node_modules/@aws-crypto/sha256-browser": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
@@ -339,6 +372,227 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@aws-sdk/client-dynamodb": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.946.0.tgz",
+ "integrity": "sha512-sMmJRa2Y+jQ+qMzx7V3SBKsTSQzLBvSuVbMNM/YGSZkr849a4a6Frl4U8HfFj4O+o71dvQ6h5PP6vlc/fW672g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/credential-provider-node": "3.946.0",
+ "@aws-sdk/dynamodb-codec": "3.946.0",
+ "@aws-sdk/middleware-endpoint-discovery": "3.936.0",
+ "@aws-sdk/middleware-host-header": "3.936.0",
+ "@aws-sdk/middleware-logger": "3.936.0",
+ "@aws-sdk/middleware-recursion-detection": "3.936.0",
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/region-config-resolver": "3.936.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@aws-sdk/util-user-agent-browser": "3.936.0",
+ "@aws-sdk/util-user-agent-node": "3.946.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/core": "^3.18.7",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/hash-node": "^4.2.5",
+ "@smithy/invalid-dependency": "^4.2.5",
+ "@smithy/middleware-content-length": "^4.2.5",
+ "@smithy/middleware-endpoint": "^4.3.14",
+ "@smithy/middleware-retry": "^4.4.14",
+ "@smithy/middleware-serde": "^4.2.6",
+ "@smithy/middleware-stack": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.13",
+ "@smithy/util-defaults-mode-node": "^4.2.16",
+ "@smithy/util-endpoints": "^3.2.5",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-retry": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz",
+ "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz",
+ "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz",
+ "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws/lambda-invoke-store": "^0.2.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.946.0.tgz",
+ "integrity": "sha512-7QcljCraeaWQNuqmOoAyZs8KpZcuhPiqdeeKoRd397jVGNRehLFsZbIMOvwaluUDFY11oMyXOkQEERe1Zo2fCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz",
+ "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz",
+ "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-endpoints": "^3.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz",
+ "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.946.0.tgz",
+ "integrity": "sha512-a2UwwvzbK5AxHKUBupfg4s7VnkqRAHjYsuezHnKCniczmT4HZfP1NnfwwvLKEH8qaTrwenxjKSfq4UWmWkvG+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@aws-sdk/client-secrets-manager": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.758.0.tgz",
@@ -391,7 +645,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/client-sso": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/client-sso": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.758.0.tgz",
"integrity": "sha512-BoGO6IIWrLyLxQG6txJw6RT2urmbtlwfggapNCrNPyYjlXpzTSJhBYjndg7TpDATFd0SXL0zm8y/tXsUXNkdYQ==",
@@ -440,29 +694,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/core": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz",
- "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.734.0",
- "@smithy/core": "^3.1.5",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/signature-v4": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
- "fast-xml-parser": "4.4.1",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-env": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.758.0.tgz",
"integrity": "sha512-N27eFoRrO6MeUNumtNHDW9WOiwfd59LPXPqDrIa3kWL/s+fOKFHb9xIcF++bAwtcZnAxKkgpDCUP+INNZskE+w==",
@@ -478,7 +710,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-http": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-http": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.758.0.tgz",
"integrity": "sha512-Xt9/U8qUCiw1hihztWkNeIR+arg6P+yda10OuCHX6kFVx3auTlU7+hCqs3UxqniGU4dguHuftf3mRpi5/GJ33Q==",
@@ -499,7 +731,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-ini": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.758.0.tgz",
"integrity": "sha512-cymSKMcP5d+OsgetoIZ5QCe1wnp2Q/tq+uIxVdh9MbfdBBEnl9Ecq6dH6VlYS89sp4QKuxHxkWXVnbXU3Q19Aw==",
@@ -523,7 +755,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-node": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-node": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.758.0.tgz",
"integrity": "sha512-+DaMv63wiq7pJrhIQzZYMn4hSarKiizDoJRvyR7WGhnn0oQ/getX9Z0VNCV3i7lIFoLNTb7WMmQ9k7+z/uD5EQ==",
@@ -546,7 +778,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-process": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-process": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.758.0.tgz",
"integrity": "sha512-AzcY74QTPqcbXWVgjpPZ3HOmxQZYPROIBz2YINF0OQk0MhezDWV/O7Xec+K1+MPGQO3qS6EDrUUlnPLjsqieHA==",
@@ -563,7 +795,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-sso": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-sso": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.758.0.tgz",
"integrity": "sha512-x0FYJqcOLUCv8GLLFDYMXRAQKGjoM+L0BG4BiHYZRDf24yQWFCAZsCQAYKo6XZYh2qznbsW6f//qpyJ5b0QVKQ==",
@@ -582,7 +814,7 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-web-identity": {
"version": "3.758.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.758.0.tgz",
"integrity": "sha512-XGguXhBqiCXMXRxcfCAVPlMbm3VyJTou79r/3mxWddHWF0XbhaQiBIbUz6vobVTD25YQRbWSmSch7VA8kI5Lrw==",
@@ -599,6 +831,947 @@
"node": ">=18.0.0"
}
},
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/nested-clients": {
+ "version": "3.758.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz",
+ "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.758.0",
+ "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/middleware-logger": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.758.0",
+ "@aws-sdk/region-config-resolver": "3.734.0",
+ "@aws-sdk/types": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@aws-sdk/util-user-agent-browser": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.758.0",
+ "@smithy/config-resolver": "^4.0.1",
+ "@smithy/core": "^3.1.5",
+ "@smithy/fetch-http-handler": "^5.0.1",
+ "@smithy/hash-node": "^4.0.1",
+ "@smithy/invalid-dependency": "^4.0.1",
+ "@smithy/middleware-content-length": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
+ "@smithy/middleware-stack": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/node-http-handler": "^4.0.3",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.6",
+ "@smithy/types": "^4.1.0",
+ "@smithy/url-parser": "^4.0.1",
+ "@smithy/util-base64": "^4.0.0",
+ "@smithy/util-body-length-browser": "^4.0.0",
+ "@smithy/util-body-length-node": "^4.0.0",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
+ "@smithy/util-endpoints": "^3.0.1",
+ "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-retry": "^4.0.1",
+ "@smithy/util-utf8": "^4.0.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/token-providers": {
+ "version": "3.758.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz",
+ "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/nested-clients": "3.758.0",
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/shared-ini-file-loader": "^4.0.1",
+ "@smithy/types": "^4.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.946.0.tgz",
+ "integrity": "sha512-kGAs5iIVyUz4p6TX3pzG5q3cNxXnVpC4pwRC6DCSaSv9ozyPjc2d74FsK4fZ+J+ejtvCdJk72uiuQtWJc86Wuw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/middleware-host-header": "3.936.0",
+ "@aws-sdk/middleware-logger": "3.936.0",
+ "@aws-sdk/middleware-recursion-detection": "3.936.0",
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/region-config-resolver": "3.936.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@aws-sdk/util-user-agent-browser": "3.936.0",
+ "@aws-sdk/util-user-agent-node": "3.946.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/core": "^3.18.7",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/hash-node": "^4.2.5",
+ "@smithy/invalid-dependency": "^4.2.5",
+ "@smithy/middleware-content-length": "^4.2.5",
+ "@smithy/middleware-endpoint": "^4.3.14",
+ "@smithy/middleware-retry": "^4.4.14",
+ "@smithy/middleware-serde": "^4.2.6",
+ "@smithy/middleware-stack": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.13",
+ "@smithy/util-defaults-mode-node": "^4.2.16",
+ "@smithy/util-endpoints": "^3.2.5",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-retry": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz",
+ "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz",
+ "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz",
+ "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws/lambda-invoke-store": "^0.2.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.946.0.tgz",
+ "integrity": "sha512-7QcljCraeaWQNuqmOoAyZs8KpZcuhPiqdeeKoRd397jVGNRehLFsZbIMOvwaluUDFY11oMyXOkQEERe1Zo2fCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz",
+ "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz",
+ "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-endpoints": "^3.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz",
+ "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.946.0.tgz",
+ "integrity": "sha512-a2UwwvzbK5AxHKUBupfg4s7VnkqRAHjYsuezHnKCniczmT4HZfP1NnfwwvLKEH8qaTrwenxjKSfq4UWmWkvG+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.758.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.758.0.tgz",
+ "integrity": "sha512-0RswbdR9jt/XKemaLNuxi2gGr4xGlHyGxkTdhSQzCyUe9A9OPCoLl3rIESRguQEech+oJnbHk/wuiwHqTuP9sg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.734.0",
+ "@smithy/core": "^3.1.5",
+ "@smithy/node-config-provider": "^4.0.1",
+ "@smithy/property-provider": "^4.0.1",
+ "@smithy/protocol-http": "^5.0.1",
+ "@smithy/signature-v4": "^5.0.1",
+ "@smithy/smithy-client": "^4.1.6",
+ "@smithy/types": "^4.1.0",
+ "@smithy/util-middleware": "^4.0.1",
+ "fast-xml-parser": "4.4.1",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.946.0.tgz",
+ "integrity": "sha512-P4l+K6wX1tf8LmWUvZofdQ+BgCNyk6Tb9u1H10npvqpuCD+dCM4pXIBq3PQcv/juUBOvLGGREo+Govuh3lfD0Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.946.0.tgz",
+ "integrity": "sha512-/zeOJ6E7dGZQ/l2k7KytEoPJX0APIhwt0A79hPf/bUpMF4dDs2P6JmchDrotk0a0Y/MIdNF8sBQ/MEOPnBiYoQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-stream": "^4.5.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.946.0.tgz",
+ "integrity": "sha512-Pdgcra3RivWj/TuZmfFaHbqsvvgnSKO0CxlRUMMr0PgBiCnUhyl+zBktdNOeGsOPH2fUzQpYhcUjYUgVSdcSDQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/credential-provider-env": "3.946.0",
+ "@aws-sdk/credential-provider-http": "3.946.0",
+ "@aws-sdk/credential-provider-login": "3.946.0",
+ "@aws-sdk/credential-provider-process": "3.946.0",
+ "@aws-sdk/credential-provider-sso": "3.946.0",
+ "@aws-sdk/credential-provider-web-identity": "3.946.0",
+ "@aws-sdk/nested-clients": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/credential-provider-imds": "^4.2.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.946.0.tgz",
+ "integrity": "sha512-5iqLNc15u2Zx+7jOdQkIbP62N7n2031tw5hkmIG0DLnozhnk64osOh2CliiOE9x3c4P9Pf4frAwgyy9GzNTk2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/nested-clients": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.946.0.tgz",
+ "integrity": "sha512-I7URUqnBPng1a5y81OImxrwERysZqMBREG6svhhGeZgxmqcpAZ8z5ywILeQXdEOCuuES8phUp/ojzxFjPXp/eA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.946.0",
+ "@aws-sdk/credential-provider-http": "3.946.0",
+ "@aws-sdk/credential-provider-ini": "3.946.0",
+ "@aws-sdk/credential-provider-process": "3.946.0",
+ "@aws-sdk/credential-provider-sso": "3.946.0",
+ "@aws-sdk/credential-provider-web-identity": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/credential-provider-imds": "^4.2.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.946.0.tgz",
+ "integrity": "sha512-GtGHX7OGqIeVQ3DlVm5RRF43Qmf3S1+PLJv9svrdvAhAdy2bUb044FdXXqrtSsIfpzTKlHgQUiRo5MWLd35Ntw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.946.0.tgz",
+ "integrity": "sha512-LeGSSt2V5iwYey1ENGY75RmoDP3bA2iE/py8QBKW8EDA8hn74XBLkprhrK5iccOvU3UGWY8WrEKFAFGNjJOL9g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.946.0",
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/token-providers": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.946.0.tgz",
+ "integrity": "sha512-ocBCvjWfkbjxElBI1QUxOnHldsNhoU0uOICFvuRDAZAoxvypJHN3m5BJkqb7gqorBbcv3LRgmBdEnWXOAvq+7Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/nested-clients": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/dynamodb-codec": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.946.0.tgz",
+ "integrity": "sha512-doDGHfTV8nFvDOnFJDcI4lx0NR4GT6uagTFM20AoIIVngm7UEITQ0toU1uTRRyRa+52ibMktdLkv7c8OcCG6Qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/client-dynamodb": "^3.946.0"
+ }
+ },
+ "node_modules/@aws-sdk/dynamodb-codec/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/dynamodb-codec/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/endpoint-cache": {
+ "version": "3.893.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.893.0.tgz",
+ "integrity": "sha512-KSwTfyLZyNLszz5f/yoLC+LC+CRKpeJii/+zVAy7JUOQsKhSykiRUPYUx7o2Sdc4oJfqqUl26A/jSttKYnYtAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "mnemonist": "0.38.3",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/eventstream-codec": {
+ "version": "3.370.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.370.0.tgz",
+ "integrity": "sha512-PiaDMum7TNsIE3DGECSsNYwibBIPN2/e13BJbTwi6KgVx8BV2mYA3kQkaUDiy++tEpzN81Nh5OPTFVb7bvgYYg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "3.0.0",
+ "@aws-sdk/types": "3.370.0",
+ "@aws-sdk/util-hex-encoding": "3.310.0",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@aws-sdk/eventstream-codec/node_modules/@aws-sdk/types": {
+ "version": "3.370.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.370.0.tgz",
+ "integrity": "sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/eventstream-codec/node_modules/@smithy/types": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz",
+ "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/is-array-buffer": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz",
+ "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-dynamodb": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.946.0.tgz",
+ "integrity": "sha512-1qI5EZUa/E0Ex4GITb9SiY5YvXcGKCYYawGYKiacpnA+YldLzKtllwns23upiTrHLmeBHZxwrXAG1sh1UqM3tw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/util-dynamodb": "3.946.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/client-dynamodb": "^3.946.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-dynamodb/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/lib-dynamodb/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-endpoint-discovery": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.936.0.tgz",
+ "integrity": "sha512-wNJZ8PDw0eQK2x4z1q8JqiDvw9l9xd36EoklVT2CIBt8FnqGdrMGjAx93RRbH3G6Fmvwoe+D3VJXbWHBlhD0Bw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/endpoint-cache": "3.893.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-endpoint-discovery/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@aws-sdk/middleware-host-header": {
"version": "3.734.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz",
@@ -662,54 +1835,222 @@
}
},
"node_modules/@aws-sdk/nested-clients": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz",
- "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==",
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.946.0.tgz",
+ "integrity": "sha512-rjAtEguukeW8mlyEQMQI56vxFoyWlaNwowmz1p1rav948SUjtrzjHAp4TOQWhibb7AR7BUTHBCgIcyCRjBEf4g==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.758.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
- "@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.758.0",
- "@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.743.0",
- "@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.758.0",
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.5",
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/hash-node": "^4.0.1",
- "@smithy/invalid-dependency": "^4.0.1",
- "@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-retry": "^4.0.7",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.7",
- "@smithy/util-defaults-mode-node": "^4.0.7",
- "@smithy/util-endpoints": "^3.0.1",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
- "@smithy/util-utf8": "^4.0.0",
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/middleware-host-header": "3.936.0",
+ "@aws-sdk/middleware-logger": "3.936.0",
+ "@aws-sdk/middleware-recursion-detection": "3.936.0",
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/region-config-resolver": "3.936.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@aws-sdk/util-user-agent-browser": "3.936.0",
+ "@aws-sdk/util-user-agent-node": "3.946.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/core": "^3.18.7",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/hash-node": "^4.2.5",
+ "@smithy/invalid-dependency": "^4.2.5",
+ "@smithy/middleware-content-length": "^4.2.5",
+ "@smithy/middleware-endpoint": "^4.3.14",
+ "@smithy/middleware-retry": "^4.4.14",
+ "@smithy/middleware-serde": "^4.2.6",
+ "@smithy/middleware-stack": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.13",
+ "@smithy/util-defaults-mode-node": "^4.2.16",
+ "@smithy/util-endpoints": "^3.2.5",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-retry": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz",
+ "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz",
+ "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz",
+ "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws/lambda-invoke-store": "^0.2.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.946.0.tgz",
+ "integrity": "sha512-7QcljCraeaWQNuqmOoAyZs8KpZcuhPiqdeeKoRd397jVGNRehLFsZbIMOvwaluUDFY11oMyXOkQEERe1Zo2fCw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/util-endpoints": "3.936.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz",
+ "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz",
+ "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-endpoints": "^3.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz",
+ "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/types": "^4.9.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.946.0.tgz",
+ "integrity": "sha512-a2UwwvzbK5AxHKUBupfg4s7VnkqRAHjYsuezHnKCniczmT4HZfP1NnfwwvLKEH8qaTrwenxjKSfq4UWmWkvG+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@aws-sdk/region-config-resolver": {
"version": "3.734.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz",
@@ -727,17 +2068,99 @@
"node": ">=18.0.0"
}
},
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.758.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.758.0.tgz",
- "integrity": "sha512-ckptN1tNrIfQUaGWm/ayW1ddG+imbKN7HHhjFdS4VfItsP0QQOB0+Ov+tpgb4MoNR4JaUghMIVStjIeHN2ks1w==",
+ "node_modules/@aws-sdk/signature-v4": {
+ "version": "3.370.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.370.0.tgz",
+ "integrity": "sha512-Mh++NJiXoBxMzz4d8GQPNB37nqjS1gsVwjKoSAWFE67sjgsjb8D5JWRCm9CinqPoXi2iN57+1DcQalTDKQGc0A==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/nested-clients": "3.758.0",
- "@aws-sdk/types": "3.734.0",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@aws-sdk/eventstream-codec": "3.370.0",
+ "@aws-sdk/is-array-buffer": "3.310.0",
+ "@aws-sdk/types": "3.370.0",
+ "@aws-sdk/util-hex-encoding": "3.310.0",
+ "@aws-sdk/util-middleware": "3.370.0",
+ "@aws-sdk/util-uri-escape": "3.310.0",
+ "@aws-sdk/util-utf8": "3.310.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4/node_modules/@aws-sdk/types": {
+ "version": "3.370.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.370.0.tgz",
+ "integrity": "sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4/node_modules/@smithy/types": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz",
+ "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.946.0.tgz",
+ "integrity": "sha512-a5c+rM6CUPX2ExmUZ3DlbLlS5rQr4tbdoGcgBsjnAHiYx8MuMNAI+8M7wfjF13i2yvUQj5WEIddvLpayfEZj9g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.946.0",
+ "@aws-sdk/nested-clients": "3.946.0",
+ "@aws-sdk/types": "3.936.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/core": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.946.0.tgz",
+ "integrity": "sha512-u2BkbLLVbMFrEiXrko2+S6ih5sUZPlbVyRPtXOqMHlCyzr70sE8kIiD6ba223rQeIFPcYfW/wHc6k4ihW2xxVg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.936.0",
+ "@aws-sdk/xml-builder": "3.930.0",
+ "@smithy/core": "^3.18.7",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/signature-v4": "^5.3.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/types": {
+ "version": "3.936.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz",
+ "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -757,6 +2180,34 @@
"node": ">=18.0.0"
}
},
+ "node_modules/@aws-sdk/util-buffer-from": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz",
+ "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/is-array-buffer": "3.310.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-dynamodb": {
+ "version": "3.946.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.946.0.tgz",
+ "integrity": "sha512-L1i5w52Ue2R4hmvtrZQ/8hmXiGBLrv6YlWKZCU4nN45E16TDLcn0rNMR7DXbLM/vRU8/pvqrhIwJRxuR1sjy1A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/client-dynamodb": "^3.946.0"
+ }
+ },
"node_modules/@aws-sdk/util-endpoints": {
"version": "3.743.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz",
@@ -772,6 +2223,18 @@
"node": ">=18.0.0"
}
},
+ "node_modules/@aws-sdk/util-hex-encoding": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz",
+ "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@aws-sdk/util-locate-window": {
"version": "3.723.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.723.0.tgz",
@@ -784,6 +2247,30 @@
"node": ">=18.0.0"
}
},
+ "node_modules/@aws-sdk/util-middleware": {
+ "version": "3.370.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.370.0.tgz",
+ "integrity": "sha512-Jvs9FZHaQznWGLkRel3PFEP93I1n0Kp6356zxYHk3LIOmjpzoob3R+v96mzyN+dZrnhPdPubYS41qbU2F9lROg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-uri-escape": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz",
+ "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@aws-sdk/util-user-agent-browser": {
"version": "3.734.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.734.0.tgz",
@@ -820,6 +2307,81 @@
}
}
},
+ "node_modules/@aws-sdk/util-utf8": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz",
+ "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/util-buffer-from": "3.310.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-utf8-browser": {
+ "version": "3.259.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
+ "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.3.1"
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder": {
+ "version": "3.930.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz",
+ "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.9.0",
+ "fast-xml-parser": "5.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser": {
+ "version": "5.2.5",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
+ "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "strnum": "^2.1.0"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder/node_modules/strnum": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz",
+ "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/@aws/lambda-invoke-store": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz",
+ "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
@@ -3063,12 +4625,12 @@
}
},
"node_modules/@smithy/abort-controller": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz",
- "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz",
+ "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3076,15 +4638,16 @@
}
},
"node_modules/@smithy/config-resolver": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz",
- "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz",
+ "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "@smithy/util-endpoints": "^3.2.5",
+ "@smithy/util-middleware": "^4.2.5",
"tslib": "^2.6.2"
},
"engines": {
@@ -3092,18 +4655,20 @@
}
},
"node_modules/@smithy/core": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.5.tgz",
- "integrity": "sha512-HLclGWPkCsekQgsyzxLhCQLa8THWXtB5PxyYN+2O6nkyLt550KQKTlbV2D1/j5dNIQapAZM1+qFnpBFxZQkgCA==",
+ "version": "3.18.7",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.7.tgz",
+ "integrity": "sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.1.2",
- "@smithy/util-utf8": "^4.0.0",
+ "@smithy/middleware-serde": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-stream": "^4.5.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/uuid": "^1.1.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3111,15 +4676,15 @@
}
},
"node_modules/@smithy/credential-provider-imds": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz",
- "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz",
+ "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
"tslib": "^2.6.2"
},
"engines": {
@@ -3127,15 +4692,15 @@
}
},
"node_modules/@smithy/fetch-http-handler": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz",
- "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==",
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz",
+ "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-base64": "^4.0.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/querystring-builder": "^4.2.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3143,14 +4708,14 @@
}
},
"node_modules/@smithy/hash-node": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz",
- "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz",
+ "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3158,12 +4723,12 @@
}
},
"node_modules/@smithy/invalid-dependency": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz",
- "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz",
+ "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3171,9 +4736,9 @@
}
},
"node_modules/@smithy/is-array-buffer": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz",
- "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz",
+ "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3183,13 +4748,13 @@
}
},
"node_modules/@smithy/middleware-content-length": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz",
- "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz",
+ "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3197,18 +4762,18 @@
}
},
"node_modules/@smithy/middleware-endpoint": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.6.tgz",
- "integrity": "sha512-ftpmkTHIFqgaFugcjzLZv3kzPEFsBFSnq1JsIkr2mwFzCraZVhQk2gqN51OOeRxqhbPTkRFj39Qd2V91E/mQxg==",
+ "version": "4.3.14",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.14.tgz",
+ "integrity": "sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.1.5",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
- "@smithy/util-middleware": "^4.0.1",
+ "@smithy/core": "^3.18.7",
+ "@smithy/middleware-serde": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/url-parser": "^4.2.5",
+ "@smithy/util-middleware": "^4.2.5",
"tslib": "^2.6.2"
},
"engines": {
@@ -3216,32 +4781,33 @@
}
},
"node_modules/@smithy/middleware-retry": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.7.tgz",
- "integrity": "sha512-58j9XbUPLkqAcV1kHzVX/kAR16GT+j7DUZJqwzsxh1jtz7G82caZiGyyFgUvogVfNTg3TeAOIJepGc8TXF4AVQ==",
+ "version": "4.4.14",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.14.tgz",
+ "integrity": "sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
- "tslib": "^2.6.2",
- "uuid": "^9.0.1"
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/service-error-classification": "^4.2.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-retry": "^4.2.5",
+ "@smithy/uuid": "^1.1.0",
+ "tslib": "^2.6.2"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/middleware-serde": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz",
- "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==",
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz",
+ "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3249,12 +4815,12 @@
}
},
"node_modules/@smithy/middleware-stack": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz",
- "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz",
+ "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3262,14 +4828,14 @@
}
},
"node_modules/@smithy/node-config-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz",
- "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==",
+ "version": "4.3.5",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz",
+ "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/shared-ini-file-loader": "^4.4.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3277,15 +4843,15 @@
}
},
"node_modules/@smithy/node-http-handler": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.3.tgz",
- "integrity": "sha512-dYCLeINNbYdvmMLtW0VdhW1biXt+PPCGazzT5ZjKw46mOtdgToQEwjqZSS9/EN8+tNs/RO0cEWG044+YZs97aA==",
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz",
+ "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/abort-controller": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/querystring-builder": "^4.2.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3293,12 +4859,12 @@
}
},
"node_modules/@smithy/property-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz",
- "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz",
+ "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3306,12 +4872,12 @@
}
},
"node_modules/@smithy/protocol-http": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz",
- "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==",
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz",
+ "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3319,13 +4885,13 @@
}
},
"node_modules/@smithy/querystring-builder": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz",
- "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz",
+ "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
- "@smithy/util-uri-escape": "^4.0.0",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-uri-escape": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3333,12 +4899,12 @@
}
},
"node_modules/@smithy/querystring-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz",
- "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz",
+ "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3346,24 +4912,24 @@
}
},
"node_modules/@smithy/service-error-classification": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz",
- "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz",
+ "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0"
+ "@smithy/types": "^4.9.0"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz",
- "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz",
+ "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3371,18 +4937,18 @@
}
},
"node_modules/@smithy/signature-v4": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz",
- "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==",
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz",
+ "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-uri-escape": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
+ "@smithy/is-array-buffer": "^4.2.0",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.5",
+ "@smithy/util-uri-escape": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3390,17 +4956,17 @@
}
},
"node_modules/@smithy/smithy-client": {
- "version": "4.1.6",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.6.tgz",
- "integrity": "sha512-UYDolNg6h2O0L+cJjtgSyKKvEKCOa/8FHYJnBobyeoeWDmNpXjwOAtw16ezyeu1ETuuLEOZbrynK0ZY1Lx9Jbw==",
+ "version": "4.9.10",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.10.tgz",
+ "integrity": "sha512-Jaoz4Jw1QYHc1EFww/E6gVtNjhoDU+gwRKqXP6C3LKYqqH2UQhP8tMP3+t/ePrhaze7fhLE8vS2q6vVxBANFTQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.1.5",
- "@smithy/middleware-endpoint": "^4.0.6",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-stream": "^4.1.2",
+ "@smithy/core": "^3.18.7",
+ "@smithy/middleware-endpoint": "^4.3.14",
+ "@smithy/middleware-stack": "^4.2.5",
+ "@smithy/protocol-http": "^5.3.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-stream": "^4.5.6",
"tslib": "^2.6.2"
},
"engines": {
@@ -3408,9 +4974,9 @@
}
},
"node_modules/@smithy/types": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz",
- "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==",
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz",
+ "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3420,13 +4986,13 @@
}
},
"node_modules/@smithy/url-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz",
- "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz",
+ "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/querystring-parser": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/querystring-parser": "^4.2.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3434,13 +5000,13 @@
}
},
"node_modules/@smithy/util-base64": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz",
- "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz",
+ "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3448,9 +5014,9 @@
}
},
"node_modules/@smithy/util-body-length-browser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz",
- "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz",
+ "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3460,9 +5026,9 @@
}
},
"node_modules/@smithy/util-body-length-node": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz",
- "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz",
+ "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3472,12 +5038,12 @@
}
},
"node_modules/@smithy/util-buffer-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz",
- "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz",
+ "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/is-array-buffer": "^4.0.0",
+ "@smithy/is-array-buffer": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3485,9 +5051,9 @@
}
},
"node_modules/@smithy/util-config-provider": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz",
- "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz",
+ "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3497,15 +5063,14 @@
}
},
"node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.7.tgz",
- "integrity": "sha512-CZgDDrYHLv0RUElOsmZtAnp1pIjwDVCSuZWOPhIOBvG36RDfX1Q9+6lS61xBf+qqvHoqRjHxgINeQz47cYFC2Q==",
+ "version": "4.3.13",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.13.tgz",
+ "integrity": "sha512-hlVLdAGrVfyNei+pKIgqDTxfu/ZI2NSyqj4IDxKd5bIsIqwR/dSlkxlPaYxFiIaDVrBy0he8orsFy+Cz119XvA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
- "bowser": "^2.11.0",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3513,17 +5078,17 @@
}
},
"node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.7.tgz",
- "integrity": "sha512-79fQW3hnfCdrfIi1soPbK3zmooRFnLpSx3Vxi6nUlqaaQeC5dm8plt4OTNDNqEEEDkvKghZSaoti684dQFVrGQ==",
+ "version": "4.2.16",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.16.tgz",
+ "integrity": "sha512-F1t22IUiJLHrxW9W1CQ6B9PN+skZ9cqSuzB18Eh06HrJPbjsyZ7ZHecAKw80DQtyGTRcVfeukKaCRYebFwclbg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/credential-provider-imds": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.6",
- "@smithy/types": "^4.1.0",
+ "@smithy/config-resolver": "^4.4.3",
+ "@smithy/credential-provider-imds": "^4.2.5",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/property-provider": "^4.2.5",
+ "@smithy/smithy-client": "^4.9.10",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3531,13 +5096,13 @@
}
},
"node_modules/@smithy/util-endpoints": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz",
- "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==",
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz",
+ "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/node-config-provider": "^4.3.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3545,9 +5110,9 @@
}
},
"node_modules/@smithy/util-hex-encoding": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz",
- "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz",
+ "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3557,12 +5122,12 @@
}
},
"node_modules/@smithy/util-middleware": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz",
- "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz",
+ "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3570,13 +5135,13 @@
}
},
"node_modules/@smithy/util-retry": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz",
- "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz",
+ "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/service-error-classification": "^4.2.5",
+ "@smithy/types": "^4.9.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3584,18 +5149,18 @@
}
},
"node_modules/@smithy/util-stream": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz",
- "integrity": "sha512-44PKEqQ303d3rlQuiDpcCcu//hV8sn+u2JBo84dWCE0rvgeiVl0IlLMagbU++o0jCWhYCsHaAt9wZuZqNe05Hw==",
+ "version": "4.5.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz",
+ "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/node-http-handler": "^4.0.3",
- "@smithy/types": "^4.1.0",
- "@smithy/util-base64": "^4.0.0",
- "@smithy/util-buffer-from": "^4.0.0",
- "@smithy/util-hex-encoding": "^4.0.0",
- "@smithy/util-utf8": "^4.0.0",
+ "@smithy/fetch-http-handler": "^5.3.6",
+ "@smithy/node-http-handler": "^4.4.5",
+ "@smithy/types": "^4.9.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3603,9 +5168,9 @@
}
},
"node_modules/@smithy/util-uri-escape": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz",
- "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz",
+ "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3615,12 +5180,38 @@
}
},
"node_modules/@smithy/util-utf8": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz",
- "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz",
+ "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.5.tgz",
+ "integrity": "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.2.5",
+ "@smithy/types": "^4.9.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/uuid": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz",
+ "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/util-buffer-from": "^4.0.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -10041,6 +11632,15 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/mnemonist": {
+ "version": "0.38.3",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
+ "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
+ "license": "MIT",
+ "dependencies": {
+ "obliterator": "^1.6.1"
+ }
+ },
"node_modules/module-details-from-path": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz",
@@ -10318,6 +11918,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/obliterator": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
+ "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==",
+ "license": "MIT"
+ },
"node_modules/oidc-token-hash": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz",
diff --git a/package.json b/package.json
index 755c52f..17625d4 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,12 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-sdk/client-dynamodb": "^3.414.0",
"@aws-sdk/client-secrets-manager": "^3.414.0",
+ "@aws-sdk/lib-dynamodb": "^3.414.0",
+ "@aws-sdk/credential-provider-node": "^3.940.0",
+ "@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
"@dadosfera/protospack-v2": "3.38.0-beta.10",
@@ -78,8 +83,8 @@
"multer": "1.4.5-lts.1"
},
"devDependencies": {
- "@types/cookie-parser": "^1.4.9",
"@types/cache-manager": "^4.0.6",
+ "@types/cookie-parser": "^1.4.9",
"@types/express": "^4.17.17",
"@types/express-session": "^1.18.1",
"@types/jest": "27.0.2",
diff --git a/src/app.module.ts b/src/app.module.ts
index 9de9b19..27d042c 100644
--- a/src/app.module.ts
+++ b/src/app.module.ts
@@ -33,6 +33,7 @@ import { NetworkPolicyModule } from './modules/network-policy/network-policy.mod
import { AssignModule } from './modules/assign/assign.module';
import { ShareMetadataModule } from './modules/share-metadata/share-metadata.module';
import { ApiKeyModule } from './modules/api-key/api-key.module';
+import { PlatformApiModule } from './modules/platform-api/platform-api.module';
@Module({
providers: [
@@ -73,6 +74,7 @@ import { ApiKeyModule } from './modules/api-key/api-key.module';
ApiKeyModule,
IdentityProviderModule,
NetworkPolicyModule,
+ PlatformApiModule,
//Always leave HealthModule last, so it is on the bottom of swagger
HealthModule,
],
diff --git a/src/modules/platform-api/platform-api.config.ts b/src/modules/platform-api/platform-api.config.ts
new file mode 100644
index 0000000..5875059
--- /dev/null
+++ b/src/modules/platform-api/platform-api.config.ts
@@ -0,0 +1,11 @@
+export const PLATFORM_API_CONFIG = {
+ getUrl: (): string => {
+ const url = process.env.PLATFORM_API_URL;
+ if (!url) {
+ throw new Error('PLATFORM_API_URL environment variable is not set');
+ }
+ return url;
+ },
+ region: process.env.AWS_REGION || 'us-east-1',
+ timeout: parseInt(process.env.PLATFORM_API_TIMEOUT || '30000', 10),
+};
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
new file mode 100644
index 0000000..133b239
--- /dev/null
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -0,0 +1,663 @@
+import {
+ Controller,
+ Get,
+ Post,
+ Put,
+ Patch,
+ Delete,
+ Param,
+ Body,
+ Query,
+ Inject,
+ BadRequestException,
+} from '@nestjs/common';
+import { ApiTags, ApiOperation } from '@nestjs/swagger';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+
+import {
+ Authenticated,
+ RequireAllPermissions,
+} from '../../decorators/authentication.decorator';
+import { User, RequestUser } from '../../decorators/user.decorator';
+import { PlatformApiService } from './platform-api.service';
+import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
+import { ElasticsearchService } from '../../services/elasticsearch';
+import { DynamoDBService } from '../../services/dynamodb';
+
+@ApiTags('Platform API')
+@Controller('platform')
+export class PlatformApiController {
+ private logger: any;
+
+ constructor(
+ private readonly platformApiService: PlatformApiService,
+ private readonly elasticsearchService: ElasticsearchService,
+ private readonly dynamoDBService: DynamoDBService,
+ @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
+ ) {
+ this.logger = dadosferaLogger.logger;
+ }
+
+ /**
+ * Normalize pipeline ID to match Platform-API format.
+ * Platform-API replaces '-' with '_' in pipeline IDs.
+ */
+ private normalizePipelineId(id: string): string {
+ return id?.replace(/-/g, '_') || '';
+ }
+
+ private readonly VALID_CONNECTORS = ['jdbc', 'singer', 's3'];
+
+ /**
+ * Validate that connector is provided and is a valid type.
+ */
+ private validateConnector(connector: string | undefined): void {
+ if (!connector || !this.VALID_CONNECTORS.includes(connector)) {
+ throw new BadRequestException(
+ `connector is required in job input and must be one of: ${this.VALID_CONNECTORS.join(', ')}`,
+ );
+ }
+ }
+
+ /**
+ * Map connector type to DynamoDB type.
+ * jdbc -> 'database', singer -> 'application', s3 -> 'file'
+ */
+ private mapConnectorToDynamoType(connector: string): string {
+ switch (connector) {
+ case 'jdbc':
+ return 'database';
+ case 'singer':
+ return 'application';
+ case 's3':
+ return 'file';
+ default:
+ return connector;
+ }
+ }
+
+ /**
+ * Extract and transform tables from jobs for DynamoDB input.
+ * Maps connector-specific fields to a common table format.
+ *
+ * - JDBC: load_type, table_name, column_include_list (columns), incremental_column_name (reference_column)
+ * - Singer: type maps replication_method (FULL_TABLE -> full_load, INCREMENTAL -> incremental), no columns
+ * - S3: same mapping as Singer, no columns
+ */
+ private extractTablesFromJobs(jobs: any[], connector: string): Array<{
+ name: string;
+ type: string;
+ columns?: string[];
+ reference_column?: { name: string; type: string };
+ }> {
+ if (!jobs || jobs.length === 0) return [];
+
+ const tables: Array<{
+ name: string;
+ type: string;
+ columns?: string[];
+ reference_column?: { name: string; type: string };
+ }> = [];
+
+ for (const job of jobs) {
+ const input = job.input;
+ if (!input) continue;
+
+ if (connector === 'jdbc') {
+ // JDBC: table_name, load_type, column_include_list, incremental_column_name
+ const table: {
+ name: string;
+ type: string;
+ columns?: string[];
+ reference_column?: { name: string; type: string };
+ } = {
+ name: input.table_name || '',
+ type: input.load_type || 'full_load',
+ };
+ if (input.column_include_list && input.column_include_list.length > 0) {
+ table.columns = input.column_include_list;
+ }
+ if (input.incremental_column_name) {
+ table.reference_column = {
+ name: input.incremental_column_name,
+ type: input.incremental_column_type || 'timestamp',
+ };
+ }
+ tables.push(table);
+ } else if (connector === 'singer' || connector === 's3') {
+ // Singer/S3: replication_method -> type mapping, no columns
+ let type = 'full_load';
+ if (input.replication_method === 'INCREMENTAL') {
+ type = 'incremental';
+ } else if (input.replication_method === 'FULL_TABLE') {
+ type = 'full_load';
+ }
+
+ tables.push({
+ name: input.table_name || '',
+ type,
+ });
+ }
+ }
+
+ return tables;
+ }
+
+ /**
+ * Build properties object for Elasticsearch based on connector type.
+ * Different connectors have different property structures.
+ *
+ * Note: In pi-factory flow, properties come pre-built from frontend.
+ * In Maestro proxy flow, we reconstruct from job input fields.
+ */
+ private buildPipelineProperties(jobInput: any): Record {
+ if (!jobInput) return {};
+
+ const connector = jobInput.connector;
+ const properties: Record = {};
+
+ // Determine credentials_type
+ if (jobInput.auth_parameters?.credentials_type) {
+ properties.credentials_type = jobInput.auth_parameters.credentials_type;
+ } else {
+ // Default based on connector type
+ // S3 connector typically uses iam_user, others use basic_auth
+ properties.credentials_type = connector === 's3' ? 'iam_user' : 'basic_auth';
+ }
+
+ if (connector === 'jdbc') {
+ // JDBC connectors: schema comes from table_schema
+ if (jobInput.table_schema) {
+ properties.schema = jobInput.table_schema;
+ }
+ } else if (connector === 'singer') {
+ // Singer connectors: merge config fields (dates, selected_competitions, etc.)
+ if (jobInput.config) {
+ Object.assign(properties, jobInput.config);
+ }
+ } else if (connector === 's3') {
+ // S3 connector
+ if (jobInput.engine) properties.engine = jobInput.engine;
+ if (jobInput.source_bucket) properties.source_bucket = jobInput.source_bucket;
+ if (jobInput.source_prefix) properties.source_prefix = jobInput.source_prefix;
+ if (jobInput.file_format_params) properties.file_format_params = jobInput.file_format_params;
+ }
+
+ return properties;
+ }
+
+ // ==================== PIPELINE ROUTES ====================
+
+ @Post('pipeline')
+ @ApiOperation({ summary: 'Create a new pipeline' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.CREATE)
+ async createPipeline(@Body() body: any, @User() user: RequestUser) {
+ // Validate that pipeline has jobs
+ if (!body.jobs || body.jobs.length === 0) {
+ throw new BadRequestException('Pipeline must have at least one job');
+ }
+
+ // Validate connector before proceeding
+ const firstJob = body.jobs[0]?.input;
+ this.validateConnector(firstJob?.connector);
+
+ // Inject customer_id (actually customer_name) and normalized ID into body for Platform-API
+ // Note: Platform-API was created before customer_id existed, so it expects customer_name in the customer_id field
+ const enrichedBody = {
+ ...body,
+ id: this.normalizePipelineId(body.id),
+ customer_id: user.customer_name,
+ };
+
+ const result = await this.platformApiService.proxy('POST', '/pipeline', user, enrichedBody);
+
+ // Sync to Elasticsearch and DynamoDB
+ try {
+ const plugin = firstJob?.plugin;
+ const connectorType = firstJob?.connector;
+ const connectionId = firstJob?.auth_parameters?.config_id;
+
+ // Build properties based on connector type
+ const properties = this.buildPipelineProperties(firstJob);
+
+ const connector = plugin
+ ? await this.elasticsearchService.getConnectorByPlugin(plugin)
+ : null;
+
+ // Extract tables from jobs and create DynamoDB input
+ const tables = this.extractTablesFromJobs(body.jobs, connectorType);
+ let inputId: string | undefined;
+
+ if (tables.length > 0) {
+ const inputDoc = await this.dynamoDBService.createInput(
+ user.customer_id,
+ user.user_id,
+ {
+ name: body.name,
+ description: body.description,
+ plugin: plugin || '',
+ type: this.mapConnectorToDynamoType(connectorType),
+ tables,
+ },
+ );
+ inputId = inputDoc.id;
+ this.logger.info('Created DynamoDB input for tables config', {
+ inputId,
+ pipelineId: body.id,
+ tablesCount: tables.length,
+ });
+ }
+
+ this.logger.info('Syncing pipeline to Elasticsearch', {
+ customerName: user.customer_name,
+ pipelineId: body.id,
+ plugin,
+ connector: connectorType,
+ properties,
+ inputId,
+ });
+
+ // Keep original UUID format for Elasticsearch (not normalized)
+ await this.elasticsearchService.createPipeline(
+ user.customer_name,
+ body.id,
+ {
+ name: body.name,
+ description: body.description,
+ user_id: user.user_id,
+ username: user.username,
+ customer_id: user.customer_id,
+ plugin,
+ connection_id: connectionId,
+ cron: body.cron,
+ tables: inputId,
+ properties,
+ },
+ connector,
+ );
+ } catch (error) {
+ this.logger.error('Failed to sync pipeline creation to Elasticsearch/DynamoDB', {
+ pipelineId: body.id,
+ customerName: user.customer_name,
+ error: error.message,
+ errorName: error.name,
+ });
+ }
+
+ return result;
+ }
+
+ @Get('pipelines')
+ @ApiOperation({ summary: 'List all pipelines for customer' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipelines(
+ @User() user: RequestUser,
+ @Query() query: Record,
+ ) {
+ return this.platformApiService.proxy(
+ 'GET',
+ '/pipelines',
+ user,
+ undefined,
+ query,
+ );
+ }
+
+ @Get('pipeline/:pipelineId')
+ @ApiOperation({ summary: 'Get pipeline by ID' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipeline(
+ @Param('pipelineId') pipelineId: string,
+ @User() user: RequestUser,
+ ) {
+ const normalizedId = this.normalizePipelineId(pipelineId);
+ return this.platformApiService.proxy('GET', `/pipeline/${normalizedId}`, user);
+ }
+
+ @Patch('pipeline/:pipelineId')
+ @ApiOperation({ summary: 'Update pipeline by ID' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updatePipeline(
+ @Param('pipelineId') pipelineId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ const normalizedId = this.normalizePipelineId(pipelineId);
+ const result = await this.platformApiService.proxy(
+ 'PATCH',
+ `/pipeline/${normalizedId}`,
+ user,
+ body,
+ );
+
+ // Sync to Elasticsearch (use original UUID, not normalized)
+ try {
+ await this.elasticsearchService.updatePipeline(
+ user.customer_name,
+ pipelineId,
+ {
+ name: body.name,
+ description: body.description,
+ cron: body.cron,
+ status: body.status,
+ },
+ );
+ } catch (error) {
+ this.logger.error('Failed to sync pipeline update to Elasticsearch', {
+ pipelineId,
+ error: error.message,
+ });
+ }
+
+ return result;
+ }
+
+ @Delete('pipeline/:pipelineId')
+ @ApiOperation({ summary: 'Delete pipeline by ID' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE)
+ async deletePipeline(
+ @Param('pipelineId') pipelineId: string,
+ @User() user: RequestUser,
+ ) {
+ const normalizedId = this.normalizePipelineId(pipelineId);
+ const result = await this.platformApiService.proxy(
+ 'DELETE',
+ `/pipeline/${normalizedId}`,
+ user,
+ );
+
+ // Sync to Elasticsearch (use original UUID, not normalized)
+ try {
+ await this.elasticsearchService.deletePipeline(
+ user.customer_name,
+ pipelineId,
+ );
+ } catch (error) {
+ this.logger.error('Failed to sync pipeline deletion to Elasticsearch', {
+ pipelineId,
+ error: error.message,
+ });
+ }
+
+ return result;
+ }
+
+ @Post('pipeline/execute')
+ @ApiOperation({ summary: 'Execute a pipeline' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async executePipeline(@Body() body: any, @User() user: RequestUser) {
+ return this.platformApiService.proxy('POST', '/pipeline/execute', user, body);
+ }
+
+ @Post('pipeline/pause')
+ @ApiOperation({ summary: 'Pause a pipeline' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async pausePipeline(@Body() body: any, @User() user: RequestUser) {
+ return this.platformApiService.proxy('POST', '/pipeline/pause', user, body);
+ }
+
+ @Post('pipeline/unpause')
+ @ApiOperation({ summary: 'Unpause a pipeline' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async unpausePipeline(@Body() body: any, @User() user: RequestUser) {
+ return this.platformApiService.proxy('POST', '/pipeline/unpause', user, body);
+ }
+
+ @Put('pipeline/:pipelineId/memory')
+ @ApiOperation({ summary: 'Update pipeline memory configuration' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updatePipelineMemory(
+ @Param('pipelineId') pipelineId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/pipeline/${pipelineId}/memory`,
+ user,
+ body,
+ );
+ }
+
+ // ==================== PIPELINE METADATA ROUTES ====================
+
+ @Put('pipeline/:pipelineId/metadata')
+ @ApiOperation({ summary: 'Update pipeline metadata' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updatePipelineMetadata(
+ @Param('pipelineId') pipelineId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/pipeline/${pipelineId}/metadata`,
+ user,
+ body,
+ );
+ }
+
+ @Get('pipelines/metadata')
+ @ApiOperation({ summary: 'Get all pipelines metadata' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipelinesMetadata(
+ @User() user: RequestUser,
+ @Query() query: Record,
+ ) {
+ return this.platformApiService.proxy(
+ 'GET',
+ '/pipelines/metadata',
+ user,
+ undefined,
+ query,
+ );
+ }
+
+ // ==================== PIPELINE RUN ROUTES ====================
+
+ @Post('pipeline/pipeline_run')
+ @ApiOperation({ summary: 'Create a pipeline run' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async createPipelineRun(@Body() body: any, @User() user: RequestUser) {
+ return this.platformApiService.proxy(
+ 'POST',
+ '/pipeline/pipeline_run',
+ user,
+ body,
+ );
+ }
+
+ @Get('pipeline/:pipelineId/pipeline_run')
+ @ApiOperation({ summary: 'Get pipeline runs for a pipeline' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipelineRuns(
+ @Param('pipelineId') pipelineId: string,
+ @User() user: RequestUser,
+ @Query() query: Record,
+ ) {
+ return this.platformApiService.proxy(
+ 'GET',
+ `/pipeline/${pipelineId}/pipeline_run`,
+ user,
+ undefined,
+ query,
+ );
+ }
+
+ @Get('pipeline/:pipelineId/pipeline_run/:runId')
+ @ApiOperation({ summary: 'Get specific pipeline run' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipelineRun(
+ @Param('pipelineId') pipelineId: string,
+ @Param('runId') runId: string,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'GET',
+ `/pipeline/${pipelineId}/pipeline_run/${runId}`,
+ user,
+ );
+ }
+
+ @Get('pipeline/pipeline_run/:runId/logs')
+ @ApiOperation({ summary: 'Get pipeline run logs' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getPipelineRunLogs(
+ @Param('runId') runId: string,
+ @User() user: RequestUser,
+ @Query() query: Record,
+ ) {
+ return this.platformApiService.proxy(
+ 'GET',
+ `/pipeline/pipeline_run/${runId}/logs`,
+ user,
+ undefined,
+ query,
+ );
+ }
+
+ // ==================== JOBS - COLUMN EDITING ROUTES ====================
+
+ @Put('jobs/:jobId/input')
+ @ApiOperation({ summary: 'Update job input columns' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updateJobInput(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/jobs/${jobId}/input`,
+ user,
+ body,
+ );
+ }
+
+ @Patch('jobs/:jobId/input')
+ @ApiOperation({ summary: 'Partial update job input columns' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async patchJobInput(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PATCH',
+ `/jobs/${jobId}/input`,
+ user,
+ body,
+ );
+ }
+
+ @Put('jobs/:jobId/memory')
+ @ApiOperation({ summary: 'Update job memory configuration' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updateJobMemory(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/jobs/${jobId}/memory`,
+ user,
+ body,
+ );
+ }
+
+ @Post('jobs/:jobId/reset-state')
+ @ApiOperation({ summary: 'Reset job state' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async resetJobState(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'POST',
+ `/jobs/${jobId}/reset-state`,
+ user,
+ body,
+ );
+ }
+
+ // ==================== JOBS - JDBC SYNC MODE ROUTES ====================
+
+ @Get('jobs/jdbc/:jobId')
+ @ApiOperation({ summary: 'Get JDBC job details' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getJdbcJob(@Param('jobId') jobId: string, @User() user: RequestUser) {
+ return this.platformApiService.proxy('GET', `/jobs/jdbc/${jobId}`, user);
+ }
+
+ @Put('jobs/jdbc/:jobId/sync-mode')
+ @ApiOperation({ summary: 'Update JDBC job sync mode' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updateJdbcSyncMode(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/jobs/jdbc/${jobId}/sync-mode`,
+ user,
+ body,
+ );
+ }
+
+ @Get('jobs/jdbc/configs/allowed_datatypes')
+ @ApiOperation({ summary: 'Get allowed datatypes for JDBC' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getJdbcAllowedDatatypes(@User() user: RequestUser) {
+ return this.platformApiService.proxy(
+ 'GET',
+ '/jobs/jdbc/configs/allowed_datatypes',
+ user,
+ );
+ }
+
+ // ==================== JOBS - SINGER REPLICATION ROUTES ====================
+
+ @Get('jobs/singer/:jobId')
+ @ApiOperation({ summary: 'Get Singer job details' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getSingerJob(@Param('jobId') jobId: string, @User() user: RequestUser) {
+ return this.platformApiService.proxy('GET', `/jobs/singer/${jobId}`, user);
+ }
+
+ @Put('jobs/singer/:jobId/sync-mode')
+ @ApiOperation({ summary: 'Update Singer job sync mode' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
+ async updateSingerSyncMode(
+ @Param('jobId') jobId: string,
+ @Body() body: any,
+ @User() user: RequestUser,
+ ) {
+ return this.platformApiService.proxy(
+ 'PUT',
+ `/jobs/singer/${jobId}/sync-mode`,
+ user,
+ body,
+ );
+ }
+
+ // ==================== JOBS - S3 ROUTES ====================
+
+ @Get('jobs/s3/:jobId')
+ @ApiOperation({ summary: 'Get S3 job details' })
+ @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
+ async getS3Job(@Param('jobId') jobId: string, @User() user: RequestUser) {
+ return this.platformApiService.proxy('GET', `/jobs/s3/${jobId}`, user);
+ }
+
+ // ==================== HEALTH ROUTE ====================
+
+ @Get('health')
+ @ApiOperation({ summary: 'Platform API health check' })
+ @Authenticated()
+ async healthCheck(@User() user: RequestUser) {
+ return this.platformApiService.proxy('GET', '/health', user);
+ }
+}
diff --git a/src/modules/platform-api/platform-api.module.ts b/src/modules/platform-api/platform-api.module.ts
new file mode 100644
index 0000000..427032a
--- /dev/null
+++ b/src/modules/platform-api/platform-api.module.ts
@@ -0,0 +1,16 @@
+import { Module } from '@nestjs/common';
+
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+
+import { PlatformApiController } from './platform-api.controller';
+import { PlatformApiService } from './platform-api.service';
+import { ElasticsearchModule } from '../../services/elasticsearch';
+import { DynamoDBModule } from '../../services/dynamodb';
+
+@Module({
+ imports: [ElasticsearchModule, DynamoDBModule],
+ controllers: [PlatformApiController],
+ providers: [PlatformApiService, DadosferaLogger],
+ exports: [PlatformApiService],
+})
+export class PlatformApiModule {}
diff --git a/src/modules/platform-api/platform-api.service.ts b/src/modules/platform-api/platform-api.service.ts
new file mode 100644
index 0000000..97797a3
--- /dev/null
+++ b/src/modules/platform-api/platform-api.service.ts
@@ -0,0 +1,123 @@
+import { Injectable, Inject, HttpException } from '@nestjs/common';
+import { SignatureV4 } from '@aws-sdk/signature-v4';
+import { Sha256 } from '@aws-crypto/sha256-js';
+import { defaultProvider } from '@aws-sdk/credential-provider-node';
+import axios, { AxiosResponse, Method } from 'axios';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+
+import { RequestUser } from '../../decorators/user.decorator';
+import { PLATFORM_API_CONFIG } from './platform-api.config';
+
+@Injectable()
+export class PlatformApiService {
+ private signer: SignatureV4;
+ private logger: any;
+
+ constructor(
+ @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
+ ) {
+ this.logger = dadosferaLogger.logger;
+ this.signer = new SignatureV4({
+ service: 'execute-api',
+ region: PLATFORM_API_CONFIG.region,
+ credentials: defaultProvider(),
+ sha256: Sha256,
+ });
+ }
+
+ async proxy(
+ method: string,
+ path: string,
+ user: RequestUser,
+ body?: any,
+ query?: Record,
+ ): Promise {
+ const baseUrl = PLATFORM_API_CONFIG.getUrl();
+ const url = new URL(`${baseUrl}${path}`);
+
+ // Add query params
+ if (query) {
+ Object.entries(query).forEach(([key, value]) => {
+ if (value !== undefined && value !== null) {
+ url.searchParams.set(key, String(value));
+ }
+ });
+ }
+
+ const headers: Record = {
+ host: url.hostname,
+ 'content-type': 'application/json',
+ // Forward user context headers
+ // Note: platform-api expects customer_name in the 'customer_id' header (contract inconsistency)
+ 'customer_id': user.customer_name || '',
+ 'customer_name': user.customer_name || '',
+ 'x-user-id': user.user_id || '',
+ 'x-username': user.username || '',
+ 'x-customer-tier': user.customer_tier || '',
+ 'x-customer-id': user.customer_id || '',
+ };
+
+ const requestToSign = {
+ method: method.toUpperCase(),
+ protocol: url.protocol,
+ hostname: url.hostname,
+ port: url.port ? parseInt(url.port, 10) : undefined,
+ path: url.pathname + url.search,
+ headers,
+ body: body ? JSON.stringify(body) : undefined,
+ };
+
+ this.logger.info('Proxying request to platform-api', {
+ method: method.toUpperCase(),
+ path,
+ customer_id: user.customer_id,
+ user_id: user.user_id,
+ });
+
+ try {
+ // Sign with IAM v4
+ const signedRequest = await this.signer.sign(requestToSign);
+
+ const response: AxiosResponse = await axios({
+ method: method as Method,
+ url: url.href,
+ headers: signedRequest.headers as Record,
+ data: body,
+ timeout: PLATFORM_API_CONFIG.timeout,
+ validateStatus: () => true, // Don't throw on non-2xx
+ });
+
+ // Propagate non-2xx responses as HttpExceptions
+ if (response.status >= 400) {
+ throw new HttpException(response.data, response.status);
+ }
+
+ return response.data;
+ } catch (error) {
+ this.logger.error('Platform API proxy error', {
+ error: error.message,
+ status: error.response?.status,
+ path,
+ method: method.toUpperCase(),
+ });
+
+ if (error instanceof HttpException) {
+ throw error;
+ }
+
+ if (error.response) {
+ throw new HttpException(error.response.data, error.response.status);
+ }
+
+ if (error.code === 'ECONNREFUSED') {
+ throw new HttpException('Platform API service unavailable', 503);
+ }
+
+ if (error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') {
+ throw new HttpException('Platform API request timeout', 504);
+ }
+
+ throw new HttpException('Internal server error', 500);
+ }
+ }
+}
diff --git a/src/services/dynamodb/dynamodb.config.ts b/src/services/dynamodb/dynamodb.config.ts
new file mode 100644
index 0000000..011ea25
--- /dev/null
+++ b/src/services/dynamodb/dynamodb.config.ts
@@ -0,0 +1,4 @@
+export const DYNAMODB_CONFIG = {
+ region: () => process.env.AWS_REGION || 'us-east-1',
+ inputsTable: () => process.env.INPUTS_DB || 'dadosfera-inputs-prd',
+};
diff --git a/src/services/dynamodb/dynamodb.module.ts b/src/services/dynamodb/dynamodb.module.ts
new file mode 100644
index 0000000..d50d635
--- /dev/null
+++ b/src/services/dynamodb/dynamodb.module.ts
@@ -0,0 +1,9 @@
+import { Module } from '@nestjs/common';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+import { DynamoDBService } from './dynamodb.service';
+
+@Module({
+ providers: [DynamoDBService, DadosferaLogger],
+ exports: [DynamoDBService],
+})
+export class DynamoDBModule {}
diff --git a/src/services/dynamodb/dynamodb.service.ts b/src/services/dynamodb/dynamodb.service.ts
new file mode 100644
index 0000000..aead208
--- /dev/null
+++ b/src/services/dynamodb/dynamodb.service.ts
@@ -0,0 +1,148 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
+import {
+ DynamoDBDocumentClient,
+ GetCommand,
+ PutCommand,
+ DeleteCommand,
+ TranslateConfig,
+} from '@aws-sdk/lib-dynamodb';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+import { v4 as uuid } from 'uuid';
+import { DYNAMODB_CONFIG } from './dynamodb.config';
+
+export interface InputDocument {
+ id: string;
+ client_id: string;
+ user_id: string;
+ created_at: string;
+ name: string;
+ description?: string;
+ plugin: string;
+ type: string;
+ tables?: Array<{
+ name: string;
+ type: string;
+ columns?: string[];
+ reference_column?: { name: string; type: string };
+ }>;
+ credentials?: Record;
+}
+
+@Injectable()
+export class DynamoDBService {
+ private documentClient: DynamoDBDocumentClient;
+ private logger: any;
+
+ constructor(
+ @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
+ ) {
+ this.logger = dadosferaLogger.logger;
+
+ const dynamoConfig = { region: DYNAMODB_CONFIG.region() };
+ const marshallOptions: TranslateConfig = {
+ marshallOptions: {
+ removeUndefinedValues: true,
+ },
+ };
+
+ const dynamoDb = new DynamoDBClient(dynamoConfig);
+ this.documentClient = DynamoDBDocumentClient.from(dynamoDb, marshallOptions);
+ }
+
+ async createInput(
+ clientId: string,
+ userId: string,
+ data: {
+ name: string;
+ description?: string;
+ plugin: string;
+ type: string;
+ tables?: Array<{
+ name: string;
+ type: string;
+ columns?: string[];
+ reference_column?: { name: string; type: string };
+ }>;
+ },
+ ): Promise {
+ const tableName = DYNAMODB_CONFIG.inputsTable();
+ const id = uuid();
+ const created_at = new Date().toISOString();
+
+ const item: InputDocument = {
+ id,
+ client_id: clientId,
+ user_id: userId,
+ created_at,
+ name: data.name,
+ description: data.description,
+ plugin: data.plugin,
+ type: data.type,
+ tables: data.tables,
+ };
+
+ this.logger.info('DynamoDB: Creating input', {
+ tableName,
+ inputId: id,
+ plugin: data.plugin,
+ });
+
+ const putCommand = new PutCommand({
+ TableName: tableName,
+ Item: item,
+ });
+
+ try {
+ await this.documentClient.send(putCommand);
+ this.logger.info('DynamoDB: Input created successfully', { inputId: id });
+ return item;
+ } catch (error) {
+ this.logger.error('DynamoDB: Failed to create input', {
+ tableName,
+ inputId: id,
+ region: DYNAMODB_CONFIG.region(),
+ error: error.message,
+ errorName: error.name,
+ });
+ throw error;
+ }
+ }
+
+ async findInput(clientId: string, inputId: string): Promise {
+ const tableName = DYNAMODB_CONFIG.inputsTable();
+
+ const getCommand = new GetCommand({
+ TableName: tableName,
+ Key: {
+ id: inputId,
+ client_id: clientId,
+ },
+ });
+
+ const { Item } = await this.documentClient.send(getCommand);
+
+ return Item as InputDocument | null;
+ }
+
+ async deleteInput(clientId: string, inputId: string): Promise {
+ const tableName = DYNAMODB_CONFIG.inputsTable();
+
+ this.logger.info('DynamoDB: Deleting input', {
+ tableName,
+ inputId,
+ });
+
+ const deleteCommand = new DeleteCommand({
+ TableName: tableName,
+ Key: {
+ id: inputId,
+ client_id: clientId,
+ },
+ });
+
+ await this.documentClient.send(deleteCommand);
+
+ this.logger.info('DynamoDB: Input deleted successfully', { inputId });
+ }
+}
diff --git a/src/services/dynamodb/index.ts b/src/services/dynamodb/index.ts
new file mode 100644
index 0000000..c47362e
--- /dev/null
+++ b/src/services/dynamodb/index.ts
@@ -0,0 +1,3 @@
+export * from './dynamodb.service';
+export * from './dynamodb.module';
+export * from './dynamodb.config';
diff --git a/src/services/elasticsearch/elasticsearch.config.ts b/src/services/elasticsearch/elasticsearch.config.ts
new file mode 100644
index 0000000..b20d7fe
--- /dev/null
+++ b/src/services/elasticsearch/elasticsearch.config.ts
@@ -0,0 +1,5 @@
+export const ELASTICSEARCH_CONFIG = {
+ getUrl: () => process.env.ELASTICSEARCH_URL || 'http://localhost:9200',
+ getApiKey: () => process.env.ELASTICSEARCH_API_KEY || '',
+ timeout: 10000, // 10 seconds
+};
diff --git a/src/services/elasticsearch/elasticsearch.module.ts b/src/services/elasticsearch/elasticsearch.module.ts
new file mode 100644
index 0000000..4d9d816
--- /dev/null
+++ b/src/services/elasticsearch/elasticsearch.module.ts
@@ -0,0 +1,9 @@
+import { Module } from '@nestjs/common';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+import { ElasticsearchService } from './elasticsearch.service';
+
+@Module({
+ providers: [ElasticsearchService, DadosferaLogger],
+ exports: [ElasticsearchService],
+})
+export class ElasticsearchModule {}
diff --git a/src/services/elasticsearch/elasticsearch.service.ts b/src/services/elasticsearch/elasticsearch.service.ts
new file mode 100644
index 0000000..e03b127
--- /dev/null
+++ b/src/services/elasticsearch/elasticsearch.service.ts
@@ -0,0 +1,375 @@
+import { Injectable, Inject } from '@nestjs/common';
+import axios, { AxiosInstance, AxiosError } from 'axios';
+import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
+import { ELASTICSEARCH_CONFIG } from './elasticsearch.config';
+
+interface MultiLang {
+ 'en-us': string;
+ 'pt-br': string;
+ 'es-es': string;
+}
+
+interface MultiLangArray {
+ 'en-us': string[];
+ 'pt-br': string[];
+ 'es-es': string[];
+}
+
+interface ConnectorInfo {
+ plugin: string;
+ name: MultiLang;
+ image: string;
+ version: string;
+ tags: string[];
+}
+
+interface PipelineDocument {
+ id: string;
+ name: MultiLang;
+ description: MultiLang;
+ customer_id: string;
+ user_id: string;
+ username: string;
+ status: string;
+ created_at: string;
+ updated_at: string;
+ last_status_updated: string;
+ tags: string[];
+ // Connector metadata
+ connection_id: string;
+ connector_name: string;
+ connector_plugin: string;
+ connector_version: string;
+ image_url: string;
+ // Config
+ config: {
+ cron: string;
+ tables?: string;
+ };
+ properties: string;
+ type: string;
+ in_use: number;
+ keywords: MultiLangArray;
+}
+
+@Injectable()
+export class ElasticsearchService {
+ private client: AxiosInstance;
+ private logger: any;
+
+ constructor(
+ @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
+ ) {
+ this.logger = dadosferaLogger.logger;
+ this.client = axios.create({
+ baseURL: ELASTICSEARCH_CONFIG.getUrl(),
+ headers: {
+ Authorization: `ApiKey ${ELASTICSEARCH_CONFIG.getApiKey()}`,
+ 'Content-Type': 'application/json',
+ },
+ timeout: ELASTICSEARCH_CONFIG.timeout,
+ });
+ }
+
+ private getIndex(customerName: string): string {
+ return `${customerName}_pipelines`;
+ }
+
+ private formatMultiLang(value: string): MultiLang {
+ return {
+ 'en-us': value,
+ 'pt-br': value,
+ 'es-es': value,
+ };
+ }
+
+ private formatMultiLangArray(value: string[] = []): MultiLangArray {
+ return {
+ 'en-us': value,
+ 'pt-br': value,
+ 'es-es': value,
+ };
+ }
+
+ buildPipelineDocument(
+ pipelineId: string,
+ data: {
+ name: string;
+ description?: string;
+ user_id: string;
+ username: string;
+ customer_id: string;
+ plugin: string;
+ connection_id: string;
+ cron?: string;
+ tables?: string;
+ properties?: Record;
+ type?: string;
+ status?: string;
+ created_at?: string;
+ keywords?: string[];
+ },
+ connector: ConnectorInfo | null,
+ ): PipelineDocument {
+ const now = new Date().toISOString();
+
+ return {
+ id: pipelineId,
+ connection_id: data.connection_id,
+ connector_name: connector?.name?.['en-us'] || '',
+ connector_plugin: connector?.plugin || data.plugin,
+ connector_version: connector?.version || '1.0.0',
+ created_at: data.created_at || now,
+ updated_at: now,
+ customer_id: data.customer_id,
+ description: this.formatMultiLang(data.description || ''),
+ image_url: connector?.image || '',
+ keywords: this.formatMultiLangArray(data.keywords),
+ name: this.formatMultiLang(data.name || ''),
+ status: data.status || 'CREATED',
+ user_id: data.user_id,
+ username: data.username,
+ config: {
+ cron: data.cron,
+ tables: data.tables,
+ },
+ properties: data.properties ? JSON.stringify(data.properties) : '{}',
+ type: data.type,
+ in_use: 1,
+ last_status_updated: now,
+ tags: connector?.tags || [],
+ };
+ }
+
+ async getConnectorByPlugin(plugin: string): Promise {
+ this.logger.info('Elasticsearch: Looking up connector', { plugin });
+
+ try {
+ const response = await this.client.post('/connectors/_search', {
+ query: {
+ term: { plugin: plugin },
+ },
+ size: 1,
+ });
+
+ const hits = response.data.hits?.hits || [];
+ if (hits.length === 0) {
+ this.logger.warn('Elasticsearch: Connector not found', { plugin });
+ return null;
+ }
+
+ const source = hits[0]._source;
+ return {
+ plugin: source.plugin,
+ name: source.name,
+ image: source.image,
+ version: source.version,
+ tags: source.tags || [],
+ };
+ } catch (error) {
+ this.handleError('getConnectorByPlugin', error, { plugin });
+ return null;
+ }
+ }
+
+ async createPipeline(
+ customerName: string,
+ pipelineId: string,
+ data: {
+ name: string;
+ description?: string;
+ user_id: string;
+ username: string;
+ customer_id: string;
+ status?: string;
+ created_at?: string;
+ plugin: string;
+ connection_id: string;
+ cron?: string;
+ tables?: string;
+ properties?: Record;
+ type?: string;
+ },
+ connector: ConnectorInfo | null,
+ ): Promise {
+ const index = this.getIndex(customerName);
+ const document = this.buildPipelineDocument(pipelineId, data, connector);
+
+ this.logger.info('Elasticsearch: Creating pipeline', {
+ index,
+ pipelineId,
+ plugin: document.connector_plugin,
+ });
+
+ try {
+ const response = await this.client.post(
+ `${index}/_doc/${pipelineId}`,
+ document,
+ { params: { refresh: 'wait_for' } },
+ );
+
+ this.logger.info('Elasticsearch: Pipeline created successfully', {
+ pipelineId,
+ result: response.data.result,
+ });
+
+ return response.data;
+ } catch (error) {
+ this.handleError('createPipeline', error, { pipelineId, index });
+ throw error;
+ }
+ }
+
+ async updatePipeline(
+ customerName: string,
+ pipelineId: string,
+ changes: {
+ name?: string;
+ description?: string;
+ cron?: string;
+ status?: string;
+ tags?: string[];
+ },
+ ): Promise {
+ const index = this.getIndex(customerName);
+ const now = new Date().toISOString();
+
+ const formattedChanges: Record = {
+ updated_at: now,
+ };
+
+ if (changes.name !== undefined) {
+ formattedChanges.name = this.formatMultiLang(changes.name);
+ }
+
+ if (changes.description !== undefined) {
+ formattedChanges.description = this.formatMultiLang(changes.description);
+ }
+
+ if (changes.cron !== undefined) {
+ // Update cron inside config object using ES script
+ formattedChanges.config = { cron: changes.cron };
+ }
+
+ if (changes.status !== undefined) {
+ formattedChanges.status = changes.status;
+ formattedChanges.last_status_updated = now;
+ }
+
+ if (changes.tags !== undefined) {
+ formattedChanges.tags = changes.tags;
+ }
+
+ this.logger.info('Elasticsearch: Updating pipeline', {
+ index,
+ pipelineId,
+ fields: Object.keys(formattedChanges),
+ });
+
+ try {
+ // Use script for partial config update to preserve other config fields
+ const updateBody = changes.cron !== undefined
+ ? {
+ script: {
+ source: `
+ ctx._source.updated_at = params.updated_at;
+ if (params.name != null) ctx._source.name = params.name;
+ if (params.description != null) ctx._source.description = params.description;
+ if (params.cron != null) ctx._source.config.cron = params.cron;
+ if (params.status != null) {
+ ctx._source.status = params.status;
+ ctx._source.last_status_updated = params.last_status_updated;
+ }
+ if (params.tags != null) ctx._source.tags = params.tags;
+ `,
+ params: {
+ updated_at: now,
+ name: changes.name !== undefined ? this.formatMultiLang(changes.name) : null,
+ description: changes.description !== undefined ? this.formatMultiLang(changes.description) : null,
+ cron: changes.cron || null,
+ status: changes.status || null,
+ last_status_updated: changes.status !== undefined ? now : null,
+ tags: changes.tags || null,
+ },
+ },
+ }
+ : { doc: formattedChanges };
+
+ const response = await this.client.post(
+ `${index}/_update/${pipelineId}`,
+ updateBody,
+ { params: { refresh: 'wait_for' } },
+ );
+
+ this.logger.info('Elasticsearch: Pipeline updated successfully', {
+ pipelineId,
+ result: response.data.result,
+ });
+
+ return response.data;
+ } catch (error) {
+ this.handleError('updatePipeline', error, { pipelineId, index });
+ throw error;
+ }
+ }
+
+ async deletePipeline(
+ customerName: string,
+ pipelineId: string,
+ ): Promise {
+ const index = this.getIndex(customerName);
+
+ this.logger.info('Elasticsearch: Deleting pipeline', {
+ index,
+ pipelineId,
+ });
+
+ try {
+ const response = await this.client.delete(
+ `${index}/_doc/${pipelineId}`,
+ { params: { refresh: 'wait_for' } },
+ );
+
+ this.logger.info('Elasticsearch: Pipeline deleted successfully', {
+ pipelineId,
+ result: response.data.result,
+ });
+
+ return response.data;
+ } catch (error) {
+ // If document not found, log warning but don't throw
+ if (error instanceof AxiosError && error.response?.status === 404) {
+ this.logger.warn('Elasticsearch: Pipeline not found for deletion', {
+ pipelineId,
+ index,
+ });
+ return { result: 'not_found' };
+ }
+
+ this.handleError('deletePipeline', error, { pipelineId, index });
+ throw error;
+ }
+ }
+
+ private handleError(
+ operation: string,
+ error: any,
+ context: Record,
+ ): void {
+ if (error instanceof AxiosError) {
+ this.logger.error(`Elasticsearch: ${operation} failed`, {
+ ...context,
+ status: error.response?.status,
+ statusText: error.response?.statusText,
+ errorData: error.response?.data,
+ message: error.message,
+ });
+ } else {
+ this.logger.error(`Elasticsearch: ${operation} failed`, {
+ ...context,
+ message: error.message,
+ stack: error.stack,
+ });
+ }
+ }
+}
diff --git a/src/services/elasticsearch/index.ts b/src/services/elasticsearch/index.ts
new file mode 100644
index 0000000..852bfc9
--- /dev/null
+++ b/src/services/elasticsearch/index.ts
@@ -0,0 +1,3 @@
+export * from './elasticsearch.module';
+export * from './elasticsearch.service';
+export * from './elasticsearch.config';
From 2f140d213a8bcf68f4181ca16304fdd31c014845 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Wed, 10 Dec 2025 16:51:17 +0000
Subject: [PATCH 13/41] catalogo: alteracao nas pastas e acrescimo de filtros
---
docsfera.json | 20 ++++++++
src/modules/catalog/catalog.service.ts | 54 ++++++++++++++++++++--
src/modules/catalog/dtos/index.ts | 6 +++
src/modules/catalog/share/share.service.ts | 4 +-
4 files changed, 79 insertions(+), 5 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index ab3a2c1..9cb09aa 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -3877,6 +3877,16 @@
],
"type": "string"
}
+ },
+ {
+ "name": "owner",
+ "required": false,
+ "in": "query",
+ "description": "ID do usuário owner para filtrar data assets",
+ "example": "user-id-1,user-id-2",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -4006,6 +4016,16 @@
],
"type": "string"
}
+ },
+ {
+ "name": "owner",
+ "required": false,
+ "in": "query",
+ "description": "ID do usuário owner para filtrar data assets",
+ "example": "user-id-1,user-id-2",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 1848dcd..4fd9619 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -209,10 +209,58 @@ class CatalogService implements OnModuleInit {
metadata: Metadata,
customer_id: string,
) {
- this.logger.info('CatalogService - searchDataAssets');
+ this.logger.info('CatalogService - searchDataAssets', { query });
const { search, page, size, sort_by, order, ...filters } = query;
+ this.logger.debug('Extracted filters:', { filters });
+
+ if (filters.owner) {
+ const { users: customer_users } =
+ await this.userService.findAllUsersByCustomerId(customer_id);
+
+ this.logger.info('Available users in database count:', { count: customer_users.length });
+ this.logger.info('First 5 users:', {
+ users: customer_users.slice(0, 5).map(u => ({ id: u.id, email: u.email, name: u.name }))
+ });
+
+ const ownerValues = Array.isArray(filters.owner)
+ ? filters.owner
+ : (typeof filters.owner === 'string' && filters.owner.includes(',')
+ ? filters.owner.split(',').map((o: string) => o.trim())
+ : [filters.owner]);
+
+ this.logger.info('Owner values to convert:', { ownerValues, ownerFiltersOriginal: filters.owner });
+
+ const ownerIds = ownerValues
+ .map((ownerValue: string) => {
+ const normalizedOwner = ownerValue.replace(/\s/g, '+');
+ const user = customer_users.find(u => {
+ const isIdMatch = u.id === ownerValue;
+ const isEmailMatch = u.email === ownerValue || u.email === normalizedOwner;
+ const isNameMatch = u.name === ownerValue || u.name === normalizedOwner;
+ this.logger.info('Comparing:', {
+ userId: u.id,
+ userEmail: u.email,
+ userName: u.name,
+ filterValue: ownerValue,
+ normalizedFilter: normalizedOwner,
+ idMatch: isIdMatch,
+ emailMatch: isEmailMatch,
+ nameMatch: isNameMatch,
+ });
+ return isIdMatch || isEmailMatch || isNameMatch;
+ });
+ this.logger.info('Looking for owner result:', { ownerValue, found: !!user, userId: user?.id });
+ return user?.id || ownerValue;
+ })
+ .filter((id: string) => id);
+
+ if (ownerIds.length > 0) {
+ filters.owner = ownerIds;
+ }
+ }
+
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
{
@@ -404,7 +452,7 @@ class CatalogService implements OnModuleInit {
return data_assets.map((data_asset) => {
const owner = customer_users.find(
(u) => u.id === data_asset.owner,
- )?.username;
+ )?.email;
const roles = [];
const users = [];
@@ -417,7 +465,7 @@ class CatalogService implements OnModuleInit {
const data_asset_users = data_asset?.users || []
for (const user_id of data_asset_users) {
const user = customer_users.find((r) => r.id === user_id);
- if (user) users.push({ id: user.id, username: user.username });
+ if (user) users.push({ id: user.id, email: user.email });
}
return {
...data_asset,
diff --git a/src/modules/catalog/dtos/index.ts b/src/modules/catalog/dtos/index.ts
index ef12e78..59de404 100644
--- a/src/modules/catalog/dtos/index.ts
+++ b/src/modules/catalog/dtos/index.ts
@@ -147,6 +147,12 @@ export class ICatalogAllRequest {
description: 'Tipo de ordenação - `asc`: crescente; `desc`: decrescente ',
})
order?: OrderEnum;
+
+ @ApiPropertyOptional({
+ description: 'ID do usuário owner para filtrar data assets',
+ example: 'user-id-1,user-id-2',
+ })
+ owner?: string;
}
export class ICatalogAllResponse {
diff --git a/src/modules/catalog/share/share.service.ts b/src/modules/catalog/share/share.service.ts
index 3e088a6..48f2d5c 100644
--- a/src/modules/catalog/share/share.service.ts
+++ b/src/modules/catalog/share/share.service.ts
@@ -180,7 +180,7 @@ export class ShareService implements OnModuleInit {
return data_assets.map((data_asset) => {
const owner = customer_users.find(
(u) => u.id === data_asset.owner,
- )?.username;
+ )?.email;
const roles = [];
const users = [];
@@ -190,7 +190,7 @@ export class ShareService implements OnModuleInit {
}
for (const user_id of data_asset.users) {
const user = customer_users.find((r) => r.id === user_id);
- if (user) users.push({ id: user.id, username: user.username });
+ if (user) users.push({ id: user.id, email: user.email });
}
return {
...data_asset,
From f7efb757bf31a85880f909af7d363ddb79815180 Mon Sep 17 00:00:00 2001
From: Rafael
Date: Wed, 10 Dec 2025 13:56:49 -0300
Subject: [PATCH 14/41] FEAT: add schedule limit validation and improve ES
update
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add cron-validation utility with Airflow presets support (@once, @daily, etc.)
- Validate cron expressions against customer scheduleLimit from DUC
- Fetch scheduleLimit via gRPC to ensure up-to-date configuration
- Improve ES updatePipeline to fetch current doc and merge changes
- Only update fields explicitly provided in PATCH request body
- Preserve config.tables when updating config.cron
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
.../platform-api/platform-api.controller.ts | 47 ++++++++--
.../platform-api/platform-api.module.ts | 3 +-
.../elasticsearch/elasticsearch.service.ts | 92 ++++++++-----------
src/utils/cron-validation.ts | 90 ++++++++++++++++++
4 files changed, 169 insertions(+), 63 deletions(-)
create mode 100644 src/utils/cron-validation.ts
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 133b239..d9006ef 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -23,6 +23,8 @@ import { PlatformApiService } from './platform-api.service';
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
import { ElasticsearchService } from '../../services/elasticsearch';
import { DynamoDBService } from '../../services/dynamodb';
+import { CustomersService } from '../customers/customers.service';
+import { validateCronAgainstScheduleLimit } from '../../utils/cron-validation';
@ApiTags('Platform API')
@Controller('platform')
@@ -33,6 +35,7 @@ export class PlatformApiController {
private readonly platformApiService: PlatformApiService,
private readonly elasticsearchService: ElasticsearchService,
private readonly dynamoDBService: DynamoDBService,
+ private readonly customersService: CustomersService,
@Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger,
) {
this.logger = dadosferaLogger.logger;
@@ -59,6 +62,22 @@ export class PlatformApiController {
}
}
+ /**
+ * Validate cron expression against customer's schedule limit.
+ * Fetches current scheduleLimit from DUC to ensure up-to-date configuration.
+ */
+ private async validateScheduleLimit(cron: string, customerId: string): Promise {
+ if (!cron) return;
+
+ const { customer } = await this.customersService.getCustomer(customerId);
+ const scheduleLimit = customer?.scheduleLimit || 'day';
+
+ const result = validateCronAgainstScheduleLimit(cron, scheduleLimit);
+ if (!result.valid) {
+ throw new BadRequestException(result.message);
+ }
+ }
+
/**
* Map connector type to DynamoDB type.
* jdbc -> 'database', singer -> 'application', s3 -> 'file'
@@ -201,6 +220,9 @@ export class PlatformApiController {
const firstJob = body.jobs[0]?.input;
this.validateConnector(firstJob?.connector);
+ // Validate cron against customer's schedule limit
+ await this.validateScheduleLimit(body.cron, user.customer_id);
+
// Inject customer_id (actually customer_name) and normalized ID into body for Platform-API
// Note: Platform-API was created before customer_id existed, so it expects customer_name in the customer_id field
const enrichedBody = {
@@ -322,6 +344,11 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
+ // Validate cron against customer's schedule limit if cron is being updated
+ if (body.cron) {
+ await this.validateScheduleLimit(body.cron, user.customer_id);
+ }
+
const normalizedId = this.normalizePipelineId(pipelineId);
const result = await this.platformApiService.proxy(
'PATCH',
@@ -331,16 +358,24 @@ export class PlatformApiController {
);
// Sync to Elasticsearch (use original UUID, not normalized)
+ // Only pass fields that are explicitly provided in the request body
try {
+ const esChanges: {
+ name?: string;
+ description?: string;
+ cron?: string;
+ status?: string;
+ } = {};
+
+ if ('name' in body) esChanges.name = body.name;
+ if ('description' in body) esChanges.description = body.description;
+ if ('cron' in body) esChanges.cron = body.cron;
+ if ('status' in body) esChanges.status = body.status;
+
await this.elasticsearchService.updatePipeline(
user.customer_name,
pipelineId,
- {
- name: body.name,
- description: body.description,
- cron: body.cron,
- status: body.status,
- },
+ esChanges,
);
} catch (error) {
this.logger.error('Failed to sync pipeline update to Elasticsearch', {
diff --git a/src/modules/platform-api/platform-api.module.ts b/src/modules/platform-api/platform-api.module.ts
index 427032a..c2b31e4 100644
--- a/src/modules/platform-api/platform-api.module.ts
+++ b/src/modules/platform-api/platform-api.module.ts
@@ -6,9 +6,10 @@ import { PlatformApiController } from './platform-api.controller';
import { PlatformApiService } from './platform-api.service';
import { ElasticsearchModule } from '../../services/elasticsearch';
import { DynamoDBModule } from '../../services/dynamodb';
+import { CustomersModule } from '../customers/customers.module';
@Module({
- imports: [ElasticsearchModule, DynamoDBModule],
+ imports: [ElasticsearchModule, DynamoDBModule, CustomersModule],
controllers: [PlatformApiController],
providers: [PlatformApiService, DadosferaLogger],
exports: [PlatformApiService],
diff --git a/src/services/elasticsearch/elasticsearch.service.ts b/src/services/elasticsearch/elasticsearch.service.ts
index e03b127..281b5d6 100644
--- a/src/services/elasticsearch/elasticsearch.service.ts
+++ b/src/services/elasticsearch/elasticsearch.service.ts
@@ -234,70 +234,50 @@ export class ElasticsearchService {
const index = this.getIndex(customerName);
const now = new Date().toISOString();
- const formattedChanges: Record = {
- updated_at: now,
- };
-
- if (changes.name !== undefined) {
- formattedChanges.name = this.formatMultiLang(changes.name);
- }
-
- if (changes.description !== undefined) {
- formattedChanges.description = this.formatMultiLang(changes.description);
- }
-
- if (changes.cron !== undefined) {
- // Update cron inside config object using ES script
- formattedChanges.config = { cron: changes.cron };
- }
-
- if (changes.status !== undefined) {
- formattedChanges.status = changes.status;
- formattedChanges.last_status_updated = now;
- }
-
- if (changes.tags !== undefined) {
- formattedChanges.tags = changes.tags;
- }
-
this.logger.info('Elasticsearch: Updating pipeline', {
index,
pipelineId,
- fields: Object.keys(formattedChanges),
+ fields: Object.keys(changes),
});
try {
- // Use script for partial config update to preserve other config fields
- const updateBody = changes.cron !== undefined
- ? {
- script: {
- source: `
- ctx._source.updated_at = params.updated_at;
- if (params.name != null) ctx._source.name = params.name;
- if (params.description != null) ctx._source.description = params.description;
- if (params.cron != null) ctx._source.config.cron = params.cron;
- if (params.status != null) {
- ctx._source.status = params.status;
- ctx._source.last_status_updated = params.last_status_updated;
- }
- if (params.tags != null) ctx._source.tags = params.tags;
- `,
- params: {
- updated_at: now,
- name: changes.name !== undefined ? this.formatMultiLang(changes.name) : null,
- description: changes.description !== undefined ? this.formatMultiLang(changes.description) : null,
- cron: changes.cron || null,
- status: changes.status || null,
- last_status_updated: changes.status !== undefined ? now : null,
- tags: changes.tags || null,
- },
- },
- }
- : { doc: formattedChanges };
+ // Fetch current document
+ const currentDoc = await this.client.get(`${index}/_doc/${pipelineId}`);
+ const current = currentDoc.data._source;
+
+ // Build updated document, preserving existing values
+ const updated: Record = {
+ ...current,
+ updated_at: now,
+ };
+
+ if ('name' in changes) {
+ updated.name = this.formatMultiLang(changes.name);
+ }
+
+ if ('description' in changes) {
+ updated.description = this.formatMultiLang(changes.description);
+ }
+
+ if ('cron' in changes) {
+ updated.config = {
+ ...current.config,
+ cron: changes.cron,
+ };
+ }
+
+ if ('status' in changes) {
+ updated.status = changes.status;
+ updated.last_status_updated = now;
+ }
+
+ if ('tags' in changes) {
+ updated.tags = changes.tags;
+ }
const response = await this.client.post(
- `${index}/_update/${pipelineId}`,
- updateBody,
+ `${index}/_doc/${pipelineId}`,
+ updated,
{ params: { refresh: 'wait_for' } },
);
diff --git a/src/utils/cron-validation.ts b/src/utils/cron-validation.ts
new file mode 100644
index 0000000..b46d0f6
--- /dev/null
+++ b/src/utils/cron-validation.ts
@@ -0,0 +1,90 @@
+import CronParser from 'cron-parser';
+
+export enum ScheduleLimits {
+ MINUTE = 'minute',
+ HOUR = 'hour',
+ DAY = 'day',
+ UNLIMITED = 'unlimited',
+}
+
+const SECONDS_IN_MINUTE = 60;
+const SECONDS_IN_HOUR = 3600;
+const SECONDS_IN_DAY = 86400;
+
+/**
+ * Airflow preset schedules mapped to cron expressions.
+ * @once is special - it means run only once (no recurring schedule).
+ */
+const AIRFLOW_PRESETS: Record = {
+ '@once': null, // No recurring schedule - always valid
+ '@hourly': '0 * * * *', // Every hour
+ '@daily': '0 0 * * *', // Every day at midnight
+ '@weekly': '0 0 * * 0', // Every week on Sunday
+ '@monthly': '0 0 1 * *', // First day of every month
+ '@yearly': '0 0 1 1 *', // First day of every year
+ '@annually': '0 0 1 1 *', // Same as @yearly
+};
+
+/**
+ * Convert Airflow preset to cron expression.
+ * Returns null for @once (no recurring schedule).
+ * Returns original string if not an Airflow preset.
+ */
+export function convertAirflowPresetToCron(schedule: string): string | null {
+ const preset = AIRFLOW_PRESETS[schedule.toLowerCase()];
+ if (preset !== undefined) {
+ return preset;
+ }
+ return schedule;
+}
+
+export function getMinimumIntervalSeconds(scheduleLimit: string): number {
+ switch (scheduleLimit) {
+ case ScheduleLimits.MINUTE:
+ return SECONDS_IN_MINUTE;
+ case ScheduleLimits.HOUR:
+ return SECONDS_IN_HOUR;
+ case ScheduleLimits.DAY:
+ return SECONDS_IN_DAY;
+ case ScheduleLimits.UNLIMITED:
+ default:
+ return 0;
+ }
+}
+
+export function getCronIntervalSeconds(cron: string): number {
+ const interval = CronParser.parseExpression(cron);
+ const nextDate = interval.next().toDate();
+ const afterNextDate = interval.next().toDate();
+ return Math.floor((afterNextDate.getTime() - nextDate.getTime()) / 1000);
+}
+
+export function validateCronAgainstScheduleLimit(
+ cron: string,
+ scheduleLimit: string,
+): { valid: boolean; message?: string } {
+ if (!cron) return { valid: true };
+
+ // Convert Airflow presets to cron expressions
+ const cronExpression = convertAirflowPresetToCron(cron);
+
+ // @once returns null - no recurring schedule, always valid
+ if (cronExpression === null) {
+ return { valid: true };
+ }
+
+ try {
+ const cronInterval = getCronIntervalSeconds(cronExpression);
+ const minInterval = getMinimumIntervalSeconds(scheduleLimit);
+
+ if (cronInterval < minInterval) {
+ return {
+ valid: false,
+ message: `Schedule interval (${cronInterval}s) is below customer limit (${scheduleLimit}: ${minInterval}s minimum)`,
+ };
+ }
+ return { valid: true };
+ } catch (error) {
+ return { valid: false, message: `Invalid cron expression: ${error.message}` };
+ }
+}
From 00304262bae0fe3b0429cd7478bc1b6107d67ae3 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Thu, 11 Dec 2025 13:52:58 +0000
Subject: [PATCH 15/41] FIX: wget change in helmfile
---
.github/workflows/validate-k8s.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/validate-k8s.yml b/.github/workflows/validate-k8s.yml
index 4d23e66..7f4255c 100644
--- a/.github/workflows/validate-k8s.yml
+++ b/.github/workflows/validate-k8s.yml
@@ -66,7 +66,7 @@ jobs:
- name: Install Helmfile
run: |
- wget https://github.com/helmfile/helmfile/releases/download/v0.148.0/helmfile_0.148.0_linux_amd64.tar.gz
+ curl -fsSLO https://github.com/helmfile/helmfile/releases/download/v0.148.0/helmfile_0.148.0_linux_amd64.tar.gz
tar -xzf helmfile_0.148.0_linux_amd64.tar.gz
sudo mv helmfile /usr/local/bin/
helmfile --version
From 5c29e0745046141478ba15ec4fee4beb99e50144 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Thu, 11 Dec 2025 14:07:04 +0000
Subject: [PATCH 16/41] FIX: helmfile
---
.github/workflows/validate-k8s.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/validate-k8s.yml b/.github/workflows/validate-k8s.yml
index 7f4255c..89dba0b 100644
--- a/.github/workflows/validate-k8s.yml
+++ b/.github/workflows/validate-k8s.yml
@@ -71,8 +71,10 @@ jobs:
sudo mv helmfile /usr/local/bin/
helmfile --version
- - name: Install Helm Diff Plugin
- run: helm plugin install https://github.com/databus23/helm-diff || true
+ - name: Fix Helm Diff Plugin
+ run: |
+ helm plugin rm diff || true
+ helm plugin install https://github.com/databus23/helm-diff
- name: Authenticate with OKE cluster
env:
From 6919a2a8d0a8b77c58513a85e73e8134b04d157c Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Thu, 11 Dec 2025 14:14:02 +0000
Subject: [PATCH 17/41] FIX: helmfile diff plugin
---
.github/workflows/validate-k8s.yml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/validate-k8s.yml b/.github/workflows/validate-k8s.yml
index 89dba0b..3ad7408 100644
--- a/.github/workflows/validate-k8s.yml
+++ b/.github/workflows/validate-k8s.yml
@@ -72,9 +72,16 @@ jobs:
helmfile --version
- name: Fix Helm Diff Plugin
+ env:
+ HELM_PLUGINS: /home/runner/.local/share/helm/plugins
run: |
- helm plugin rm diff || true
+ rm -rf "$HELM_PLUGINS/diff" "$HELM_PLUGINS/helm-diff" || true
+
+ mkdir -p "$HELM_PLUGINS"
+ ls -R "$HELM_PLUGINS" || true
+
helm plugin install https://github.com/databus23/helm-diff
+ helm plugin list
- name: Authenticate with OKE cluster
env:
From dd699614aeb3d1b067e0817a4c02e5f8b2759d63 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Thu, 11 Dec 2025 16:47:28 +0000
Subject: [PATCH 18/41] FIX: Maestro helm fix
---
.github/workflows/validate-k8s.yml | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/validate-k8s.yml b/.github/workflows/validate-k8s.yml
index 3ad7408..8a67a9c 100644
--- a/.github/workflows/validate-k8s.yml
+++ b/.github/workflows/validate-k8s.yml
@@ -71,17 +71,11 @@ jobs:
sudo mv helmfile /usr/local/bin/
helmfile --version
- - name: Fix Helm Diff Plugin
- env:
- HELM_PLUGINS: /home/runner/.local/share/helm/plugins
+ - name: Debug Helm env
run: |
- rm -rf "$HELM_PLUGINS/diff" "$HELM_PLUGINS/helm-diff" || true
-
- mkdir -p "$HELM_PLUGINS"
- ls -R "$HELM_PLUGINS" || true
-
- helm plugin install https://github.com/databus23/helm-diff
- helm plugin list
+ helm env
+ echo "HOME=$HOME"
+ ls -R $HOME/.local/share/helm || true
- name: Authenticate with OKE cluster
env:
From df3f2489f986823fe2dcd1b80b9f80e22470d612 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Thu, 11 Dec 2025 22:10:32 +0000
Subject: [PATCH 19/41] FIX: Calendar Fix
---
docsfera.json | 40 +++++++++++
src/modules/catalog/catalog.service.ts | 96 +++++++++++++++++++++++++-
src/modules/catalog/dtos/index.ts | 12 ++++
3 files changed, 147 insertions(+), 1 deletion(-)
diff --git a/docsfera.json b/docsfera.json
index 9cb09aa..d27ab0a 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -3887,6 +3887,26 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "catalog_date_from",
+ "required": false,
+ "in": "query",
+ "description": "Data inicial para filtro de catálogo (formato: YYYY-MM-DD)",
+ "example": "2025-01-01",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "catalog_date_to",
+ "required": false,
+ "in": "query",
+ "description": "Data final para filtro de catálogo (formato: YYYY-MM-DD)",
+ "example": "2025-12-31",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -4026,6 +4046,26 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "catalog_date_from",
+ "required": false,
+ "in": "query",
+ "description": "Data inicial para filtro de catálogo (formato: YYYY-MM-DD)",
+ "example": "2025-01-01",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "catalog_date_to",
+ "required": false,
+ "in": "query",
+ "description": "Data final para filtro de catálogo (formato: YYYY-MM-DD)",
+ "example": "2025-12-31",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 4fd9619..8d87d9c 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -39,6 +39,7 @@ import {
import { TypeParser } from 'src/utils/FileParser/parser-types';
import { ParserBuilder } from 'src/utils/FileParser/parser.builder';
+
class CatalogService implements OnModuleInit {
catalogReadService: ReadService.CatalogReadServices;
catalogWriteService: WriteService.CatalogWriteServices;
@@ -55,6 +56,7 @@ class CatalogService implements OnModuleInit {
this.logger = dadosferaLogger.logger;
}
+
onModuleInit() {
this.catalogReadService =
this.grpcClient.getService(
@@ -70,20 +72,24 @@ class CatalogService implements OnModuleInit {
);
}
+
_getNimbusUrl(body) {
this.logger.debug(`Body: ${JSON.stringify(body)}`);
const customer = body.info.customer.toLowerCase();
+
if (process.env.ENV === 'prd') {
return `https://nimbus-${customer}.dadosfera.ai`;
}
+
return `https://nimbus-${customer}.${process.env.ENV.replace(
'local',
'stg',
)}.dadosfera.ai`;
}
+
async getPiiReporter(metadata: Metadata, type: TypeParser) {
this.logger.info('getPiiReporter: ' + type)
try {
@@ -94,8 +100,10 @@ class CatalogService implements OnModuleInit {
)
this.logger.info("Finish grpc call")
+
const parser = ParserBuilder.build(type);
+
this.logger.info('parser file to: ' + type)
const file = await parser.parse(data)
this.logger.info('finish parser')
@@ -105,9 +113,11 @@ class CatalogService implements OnModuleInit {
'pdf': 'application/pdf'
}
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `relatorio-pii-${timestamp}.${type}`;
+
return {
file,
filename: filename,
@@ -118,20 +128,25 @@ class CatalogService implements OnModuleInit {
throw error;
}
+
}
+
async createDataAsset(data: Messages.CreateDataAssetRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
if (!data.embed) data.embed = undefined;
+
return lastValueFrom(
this.catalogWriteService.CreateDataAsset(data, metadata),
);
}
+
async managePermissions(data: Messages.ManagePermissionRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
+
return lastValueFrom(
this.catalogWriteService.ManagePermission(data, metadata),
).catch((err) => {
@@ -142,9 +157,11 @@ class CatalogService implements OnModuleInit {
});
}
+
async revokePermissions(data: Messages.RevokePermissionRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
+
return lastValueFrom(
this.catalogWriteService.RevokePermission(data, metadata),
).catch((err) => {
@@ -155,9 +172,11 @@ class CatalogService implements OnModuleInit {
});
}
+
async commentOnDataAsset(data: Messages.MakeACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
+
return lastValueFrom(
this.catalogWriteService.MakeAComment(data, metadata),
).catch((err) => {
@@ -168,9 +187,11 @@ class CatalogService implements OnModuleInit {
});
}
+
async deleteComment(data: Messages.UpdateACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
+
return lastValueFrom(
this.catalogWriteService.UpdateAComment(data, metadata),
).catch((err) => {
@@ -181,9 +202,11 @@ class CatalogService implements OnModuleInit {
});
}
+
async deleteDataAsset(data: Messages.DeleteDataAssetRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
+
return lastValueFrom(
this.catalogWriteService.DeleteDataAsset(data, metadata),
).catch((err) => {
@@ -194,16 +217,20 @@ class CatalogService implements OnModuleInit {
});
}
+
async getUserRolesIds(userId: string) {
const result = await this.userService.findOneById(userId).catch(() => null);
+
if (result) {
return result.user.roles.map((role) => role.id);
}
+
return [];
}
+
async searchDataAssets(
query: Record,
metadata: Metadata,
@@ -211,10 +238,19 @@ class CatalogService implements OnModuleInit {
) {
this.logger.info('CatalogService - searchDataAssets', { query });
+
const { search, page, size, sort_by, order, ...filters } = query;
+
this.logger.debug('Extracted filters:', { filters });
+
+ console.log('MAESTRO VAI CHAMAR PI-FACTORY COM:', {
+ search, page, size, sort_by, order,
+ filters: filters
+ });
+
+
if (filters.owner) {
const { users: customer_users } =
await this.userService.findAllUsersByCustomerId(customer_id);
@@ -224,6 +260,7 @@ class CatalogService implements OnModuleInit {
users: customer_users.slice(0, 5).map(u => ({ id: u.id, email: u.email, name: u.name }))
});
+
const ownerValues = Array.isArray(filters.owner)
? filters.owner
: (typeof filters.owner === 'string' && filters.owner.includes(',')
@@ -232,6 +269,7 @@ class CatalogService implements OnModuleInit {
this.logger.info('Owner values to convert:', { ownerValues, ownerFiltersOriginal: filters.owner });
+
const ownerIds = ownerValues
.map((ownerValue: string) => {
const normalizedOwner = ownerValue.replace(/\s/g, '+');
@@ -256,11 +294,13 @@ class CatalogService implements OnModuleInit {
})
.filter((id: string) => id);
+
if (ownerIds.length > 0) {
filters.owner = ownerIds;
}
}
+
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
{
@@ -275,16 +315,25 @@ class CatalogService implements OnModuleInit {
),
);
+
+
+ console.log('MAESTRO RECEBEU RESPOSTA DO PI-FACTORY');
+
+
+
const result = JSON.parse(data_assets);
+
const response = await this.getAssetsUsersAndRoles(
result.data_assets,
customer_id,
);
+
return { data_assets: response, total };
}
+
async downloadAssets(
query: Record,
metadata: Metadata,
@@ -292,6 +341,7 @@ class CatalogService implements OnModuleInit {
) {
const data = await this.searchDataAssets(query, metadata, customer_id);
+
const formatData = data.data_assets.map(asset => ({
id: asset.id,
display_name: asset.display_name,
@@ -300,19 +350,24 @@ class CatalogService implements OnModuleInit {
tags: '[' + asset.tags.join(', ') + ']'
}))
+
const parser = ParserBuilder.build('csv');
+
const file = await parser.parse(formatData);
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `dadosfera_assets_${timestamp}.csv`;
+
return {
file,
filename
}
}
+
async getOneDataAsset(data: {
id: string;
customer_id: string;
@@ -333,9 +388,11 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
+
return { data_asset: asset[0] };
}
+
async getOneDataAssetByPipelineAndObject(data: {
customer_id: string;
pipeline: string;
@@ -357,9 +414,11 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
+
return { data_asset: asset[0] };
}
+
async updateOneDataAsset(data: {
data_asset_id: string;
customer_id: string;
@@ -368,6 +427,7 @@ class CatalogService implements OnModuleInit {
}) {
const { body, customer_id, data_asset_id, metadata } = data;
+
const { data_asset } = await lastValueFrom(
this.catalogWriteService.UpdateDataAsset(
{ id: data_asset_id, changes: JSON.stringify(body) },
@@ -382,9 +442,11 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
+
return { data_asset: asset[0] };
}
+
async getDataDocs(id: string, metadata: Metadata) {
const { documentation } = await lastValueFrom(
this.catalogReadService.GetDatasetDoc({ id, type: undefined }, metadata),
@@ -394,6 +456,7 @@ class CatalogService implements OnModuleInit {
return docs;
}
+
async getDatasetPreview(id: string, metadata: Metadata) {
const { preview } = await lastValueFrom(
this.catalogReadService.GetDatasetPreview(
@@ -405,6 +468,7 @@ class CatalogService implements OnModuleInit {
return result;
}
+
async getDatasetColumnsMetadata(id: string, metadata: Metadata) {
const { columns_metadata } = await lastValueFrom(
this.catalogReadService.GetDatasetColumnsMetadata(
@@ -416,6 +480,7 @@ class CatalogService implements OnModuleInit {
return result;
}
+
async createDataDocs(body) {
const nimbusUrl = this._getNimbusUrl(body);
const { data } = await axios.post(
@@ -425,9 +490,11 @@ class CatalogService implements OnModuleInit {
return data;
}
+
async findAllTags(data, metadata) {
this.logger.info('CatalogService - findAllCustomerTags');
+
const response = await lastValueFrom(
this.catalogReadService.GetCustomerTags(data, metadata),
)
@@ -440,6 +507,7 @@ class CatalogService implements OnModuleInit {
throw new Error(err);
});
+
return response;
}
async getAssetsUsersAndRoles(data_assets: Array, customer_id: string) {
@@ -454,6 +522,7 @@ class CatalogService implements OnModuleInit {
(u) => u.id === data_asset.owner,
)?.email;
+
const roles = [];
const users = [];
const data_asset_roles = data_asset?.roles || []
@@ -462,6 +531,7 @@ class CatalogService implements OnModuleInit {
if (role) roles.push({ id: role.id, name: role.name });
}
+
const data_asset_users = data_asset?.users || []
for (const user_id of data_asset_users) {
const user = customer_users.find((r) => r.id === user_id);
@@ -476,6 +546,7 @@ class CatalogService implements OnModuleInit {
});
}
+
async triggerCatalog(data: TriggerCatalogReq, metadata: Metadata) {
const { session } = await lastValueFrom(
this.catalogWriteService.TriggerDatasetCataloging(data, metadata),
@@ -489,6 +560,7 @@ class CatalogService implements OnModuleInit {
return res;
}
+
async addRlsRule(data: AddRlsRuleRequest, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogWriteService.AddRlsRule(data, metadata),
@@ -496,6 +568,7 @@ class CatalogService implements OnModuleInit {
return res;
}
+
async removeRlsRule(id: number, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogWriteService.RemoveRlsRule({ id }, metadata),
@@ -503,12 +576,14 @@ class CatalogService implements OnModuleInit {
return res;
}
+
async batchRemoveRlsRule(
query: BatchRemoveRlsRulesRequest,
metadata: Metadata,
) {
const { id_rls, nimbus_dashboard_id } = query;
+
if (id_rls && nimbus_dashboard_id) {
throw new BadRequestException(
"You can't delete using both parameters. Choose either 'id_rls' or 'nimbus_dashboard_id'",
@@ -529,6 +604,7 @@ class CatalogService implements OnModuleInit {
return 'OK';
}
+
async getRlsRules(data: GetRlsRulesRequest, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogReadService.GetRlsRules(data, metadata),
@@ -536,6 +612,7 @@ class CatalogService implements OnModuleInit {
return res.rls_rules;
}
+
async getOneRlsRule(id: number, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogReadService.GetOneRlsRule({ id }, metadata),
@@ -543,6 +620,7 @@ class CatalogService implements OnModuleInit {
return res.rls_rule;
}
+
async getNimbusDashboards(
data: GetNimbusDashboardsRequest,
metadata: Metadata,
@@ -553,19 +631,24 @@ class CatalogService implements OnModuleInit {
return res.dashboards;
}
+
async createTableMetadata(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
this.logger.info(`Nimbus URL: ${nimbusUrl}`, {...body.logMetadata});
+
const endpoint = `${nimbusUrl}/api/catalog/table-metadata/`;
+
this.logger.info(`Creating table metadata for table ${body.table_metadata.table_name}`, {...body.logMetadata});
this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
this.logger.debug(`Payload: ${JSON.stringify(body.table_metadata)}`, {...body.logMetadata});
+
try {
const { data, status } = await axios.post(endpoint, {...body.table_metadata});
+
this.logger.info(
`Table metadata created successfully with status ${status} for table ${body.table_metadata.table_name}`,
{...body.logMetadata},
@@ -580,19 +663,23 @@ class CatalogService implements OnModuleInit {
}
}
+
async createColumnMetadata(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
this.logger.info(`Nimbus URL: ${nimbusUrl}`, body.logMetadata);
const endpoint = `${nimbusUrl}/api/catalog/column-metadata/`;
+
+
try {
this.logger.info(`Creating column metadata for table ${body.column_metadata.table_name}`, {...body.logMetadata});
this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
this.logger.debug(`Payload: ${JSON.stringify(body.column_metadata)}`, {...body.logMetadata});
const { data, status } = await axios.post(endpoint, body.column_metadata);
+
this.logger.info(
`Column metadata created successfully with status ${status} for table ${body.column_metadata.table_name}`,
{...body.logMetadata},
@@ -607,18 +694,22 @@ class CatalogService implements OnModuleInit {
}
}
+
async createDataPreview(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
this.logger.info(`Nimbus URL: ${nimbusUrl}`, {...body.logMetadata});
const endpoint = `${nimbusUrl}/api/catalog/data-preview/`;
+
this.logger.info(`Creating data preview for table ${body.data_preview.table_name}`, {...body.logMetadata});
this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
this.logger.debug(`Payload: ${JSON.stringify(body.data_preview)}`, {...body.logMetadata});
+
try {
const { data, status } = await axios.post(endpoint, body.data_preview);
+
this.logger.info(
`Data preview created successfully with status ${status} for table ${body.data_preview.table_name}`,
{...body.logMetadata},
@@ -635,9 +726,11 @@ class CatalogService implements OnModuleInit {
}
}
+
async catalogDatasetItem(table_metadata_id: number, metadata: Metadata) {
const customer_name_raw = metadata.get('customer_name');
+
const customer_name = customer_name_raw?.[0]?.toString();
if (!customer_name) {
throw new BadRequestException('Customer name not found in metadata');
@@ -660,4 +753,5 @@ class CatalogService implements OnModuleInit {
}
}
-export { CatalogService };
\ No newline at end of file
+
+export { CatalogService };
diff --git a/src/modules/catalog/dtos/index.ts b/src/modules/catalog/dtos/index.ts
index 59de404..39d2708 100644
--- a/src/modules/catalog/dtos/index.ts
+++ b/src/modules/catalog/dtos/index.ts
@@ -153,6 +153,18 @@ export class ICatalogAllRequest {
example: 'user-id-1,user-id-2',
})
owner?: string;
+
+ @ApiPropertyOptional({
+ description: 'Data inicial para filtro de catálogo (formato: YYYY-MM-DD)',
+ example: '2025-01-01',
+ })
+ catalog_date_from?: string;
+
+ @ApiPropertyOptional({
+ description: 'Data final para filtro de catálogo (formato: YYYY-MM-DD)',
+ example: '2025-12-31',
+ })
+ catalog_date_to?: string;
}
export class ICatalogAllResponse {
From 1ff5589a2e567bb6ec506f347e2648ac43608cd7 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Fri, 12 Dec 2025 15:03:43 -0300
Subject: [PATCH 20/41] FIX: Simplify searchDataAssets by owner logging and
remove log code
---
src/modules/catalog/catalog.service.ts | 67 +-------------------------
1 file changed, 1 insertion(+), 66 deletions(-)
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 27c158f..5929849 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -238,71 +238,11 @@ class CatalogService implements OnModuleInit {
metadata: Metadata,
customer_id: string,
) {
- this.logger.info('CatalogService - searchDataAssets', { query });
+ this.logger.info('CatalogService - searchDataAssets');
const { search, page, size, sort_by, order, ...filters } = query;
-
- this.logger.debug('Extracted filters:', { filters });
-
-
- console.log('MAESTRO VAI CHAMAR PI-FACTORY COM:', {
- search, page, size, sort_by, order,
- filters: filters
- });
-
-
- if (filters.owner) {
- const { users: customer_users } =
- await this.userService.findAllUsersByCustomerId(customer_id);
-
- this.logger.info('Available users in database count:', { count: customer_users.length });
- this.logger.info('First 5 users:', {
- users: customer_users.slice(0, 5).map(u => ({ id: u.id, email: u.email, name: u.name }))
- });
-
-
- const ownerValues = Array.isArray(filters.owner)
- ? filters.owner
- : (typeof filters.owner === 'string' && filters.owner.includes(',')
- ? filters.owner.split(',').map((o: string) => o.trim())
- : [filters.owner]);
-
- this.logger.info('Owner values to convert:', { ownerValues, ownerFiltersOriginal: filters.owner });
-
-
- const ownerIds = ownerValues
- .map((ownerValue: string) => {
- const normalizedOwner = ownerValue.replace(/\s/g, '+');
- const user = customer_users.find(u => {
- const isIdMatch = u.id === ownerValue;
- const isEmailMatch = u.email === ownerValue || u.email === normalizedOwner;
- const isNameMatch = u.name === ownerValue || u.name === normalizedOwner;
- this.logger.info('Comparing:', {
- userId: u.id,
- userEmail: u.email,
- userName: u.name,
- filterValue: ownerValue,
- normalizedFilter: normalizedOwner,
- idMatch: isIdMatch,
- emailMatch: isEmailMatch,
- nameMatch: isNameMatch,
- });
- return isIdMatch || isEmailMatch || isNameMatch;
- });
- this.logger.info('Looking for owner result:', { ownerValue, found: !!user, userId: user?.id });
- return user?.id || ownerValue;
- })
- .filter((id: string) => id);
-
-
- if (ownerIds.length > 0) {
- filters.owner = ownerIds;
- }
- }
-
-
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
{
@@ -318,11 +258,6 @@ class CatalogService implements OnModuleInit {
);
-
- console.log('MAESTRO RECEBEU RESPOSTA DO PI-FACTORY');
-
-
-
const result = JSON.parse(data_assets);
From 918c3d7416cbb331d38868b2e5aeb2c2b7d9d3a4 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Mon, 15 Dec 2025 09:08:08 -0300
Subject: [PATCH 21/41] FIX: Enhance searchDataAssets to convert owner names to
IDs and log the conversion
---
docsfera.json | 8 ++++++++
src/modules/catalog/catalog.service.ts | 27 ++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/docsfera.json b/docsfera.json
index 4d80f69..4f1c426 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -4483,6 +4483,14 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "asset_type",
+ "required": true,
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 5929849..9d99f7d 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -243,6 +243,33 @@ class CatalogService implements OnModuleInit {
const { search, page, size, sort_by, order, ...filters } = query;
+ if (filters.owner) {
+ const { users: customer_users } =
+ await this.userService.findAllUsersByCustomerId(customer_id);
+
+ const ownerValues = Array.isArray(filters.owner)
+ ? filters.owner
+ : (typeof filters.owner === 'string' && filters.owner.includes(',')
+ ? filters.owner.split(',').map((o: string) => o.trim())
+ : [filters.owner]);
+
+ const ownerIds = ownerValues
+ .map((ownerValue: string) => {
+ const user = customer_users.find(u =>
+ u.name === ownerValue || u.email === ownerValue || u.id === ownerValue
+ );
+ return user ? user.id : ownerValue;
+ })
+ .filter((id: string) => id);
+
+ filters.owner = ownerIds;
+
+ this.logger.info('Converted owner names to IDs:', {
+ original: ownerValues,
+ converted: ownerIds
+ });
+ }
+
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
{
From 288aaeabc0799262f16664fab42d1d6f0a9a0e98 Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Mon, 15 Dec 2025 12:00:50 -0300
Subject: [PATCH 22/41] FIX: Enhance filter handling in
BuildDataAssetsFilterTerms to support empty owner condition
---
src/modules/catalog/catalog.service.ts | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 9d99f7d..39090b1 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -240,10 +240,10 @@ class CatalogService implements OnModuleInit {
) {
this.logger.info('CatalogService - searchDataAssets');
-
const { search, page, size, sort_by, order, ...filters } = query;
-
- if (filters.owner) {
+
+ // Verificar se filters.owner existe
+ if (filters.owner !== undefined && filters.owner !== null) {
const { users: customer_users } =
await this.userService.findAllUsersByCustomerId(customer_id);
@@ -253,7 +253,11 @@ class CatalogService implements OnModuleInit {
? filters.owner.split(',').map((o: string) => o.trim())
: [filters.owner]);
- const ownerIds = ownerValues
+ // Separar "sem owner" (marcador especial __null__) dos owners normais
+ const hasEmptyOwner = ownerValues.some(v => v === '__null__');
+ const normalOwners = ownerValues.filter(v => v !== '__null__');
+
+ const ownerIds = normalOwners
.map((ownerValue: string) => {
const user = customer_users.find(u =>
u.name === ownerValue || u.email === ownerValue || u.id === ownerValue
@@ -262,13 +266,12 @@ class CatalogService implements OnModuleInit {
})
.filter((id: string) => id);
- filters.owner = ownerIds;
-
- this.logger.info('Converted owner names to IDs:', {
- original: ownerValues,
- converted: ownerIds
- });
- }
+ // Se tiver "sem owner", adicionar marcador especial
+ if (hasEmptyOwner) {
+ ownerIds.push('__null__');
+ }
+
+ filters.owner = ownerIds.length > 0 ? ownerIds : undefined;
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
From fcf7fb054e7fa4f5e3fc84fd27e2e45a4f85631a Mon Sep 17 00:00:00 2001
From: viniciusgadea
Date: Tue, 16 Dec 2025 09:55:24 -0300
Subject: [PATCH 23/41] FIX: Update searchDataAssets to handle owner filtering
and convert owner names to IDs
---
src/modules/catalog/catalog.service.ts | 46 +++++++++++++++-----------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 39090b1..c56313e 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -240,38 +240,44 @@ class CatalogService implements OnModuleInit {
) {
this.logger.info('CatalogService - searchDataAssets');
- const { search, page, size, sort_by, order, ...filters } = query;
+ const { search, page, size, sort_by, order, owner, ...filters } = query;
// Verificar se filters.owner existe
- if (filters.owner !== undefined && filters.owner !== null) {
+ if (owner !== undefined && owner !== null) {
const { users: customer_users } =
await this.userService.findAllUsersByCustomerId(customer_id);
- const ownerValues = Array.isArray(filters.owner)
- ? filters.owner
- : (typeof filters.owner === 'string' && filters.owner.includes(',')
- ? filters.owner.split(',').map((o: string) => o.trim())
- : [filters.owner]);
+ let ownerValues: string[];
+ if (Array.isArray(owner)) {
+ ownerValues = owner;
+ } else if (typeof owner === 'string' && owner.includes(',')) {
+ ownerValues = owner.split(',').map((o: string) => o.trim());
+ } else {
+ ownerValues = [owner];
+ }
- // Separar "sem owner" (marcador especial __null__) dos owners normais
- const hasEmptyOwner = ownerValues.some(v => v === '__null__');
- const normalOwners = ownerValues.filter(v => v !== '__null__');
+ // Separar "sem owner" (marcador especial null) dos owners normais
+ const hasEmptyOwner = ownerValues.some(v => v === 'null');
+ const normalOwners = ownerValues.filter(v => v !== 'null');
- const ownerIds = normalOwners
- .map((ownerValue: string) => {
- const user = customer_users.find(u =>
- u.name === ownerValue || u.email === ownerValue || u.id === ownerValue
- );
- return user ? user.id : ownerValue;
- })
- .filter((id: string) => id);
+ // Converter nomes de owners para IDs
+ const ownerIds = normalOwners.map((ownerValue: string) => {
+ const user = customer_users.find(u =>
+ u.name === ownerValue || u.email === ownerValue || u.id === ownerValue
+ );
+ return user ? user.id : ownerValue;
+ });
// Se tiver "sem owner", adicionar marcador especial
if (hasEmptyOwner) {
- ownerIds.push('__null__');
+ ownerIds.push('null');
}
- filters.owner = ownerIds.length > 0 ? ownerIds : undefined;
+ // Adicionar ao filters apenas se houver valores
+ if (ownerIds.length > 0) {
+ filters.owner = ownerIds;
+ }
+ }
const { data_assets, total } = await lastValueFrom(
this.catalogReadService.GetAllDataAssets(
From 01c1087e0725a159bb6958190d27660d055d758c Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 16:37:33 -0300
Subject: [PATCH 24/41] FEAT: add schedule limit validation and improve ES
update
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add schedule limit validation against customer's scheduleLimit from DUC
- Improve ES update to only update provided fields
- Mark GET /platform/pipeline/:pipelineId/pipeline_run as READY
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
docsfera.json | 893 +++++++++++++++++-
src/main.ts | 1 +
.../platform-api/platform-api.controller.ts | 304 +++++-
src/services/dynamodb/dynamodb.service.ts | 85 +-
.../elasticsearch/elasticsearch.service.ts | 27 +
5 files changed, 1275 insertions(+), 35 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index a18dad5..3ae0f4c 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -42,6 +42,33 @@
]
}
},
+ "/auth/sign-out": {
+ "post": {
+ "operationId": "AuthController_signOut",
+ "parameters": [
+ {
+ "name": "dadosfera-lang",
+ "in": "header",
+ "required": false,
+ "schema": {
+ "enum": [
+ "pt-br",
+ "en-us"
+ ],
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "204": {
+ "description": ""
+ }
+ },
+ "tags": [
+ "Auth"
+ ]
+ }
+ },
"/auth/refresh-access-token": {
"post": {
"operationId": "AuthController_refreshAccessToken",
@@ -3415,9 +3442,6 @@
"PipelinesV2"
],
"security": [
- {
- "access-token": []
- },
{
"access-token": []
}
@@ -3467,9 +3491,6 @@
"PipelinesV2"
],
"security": [
- {
- "access-token": []
- },
{
"access-token": []
}
@@ -3519,9 +3540,6 @@
"PipelinesV2"
],
"security": [
- {
- "access-token": []
- },
{
"access-token": []
}
@@ -6760,6 +6778,863 @@
}
}
},
+ "/platform/pipeline": {
+ "post": {
+ "operationId": "PlatformApiController_createPipeline",
+ "summary": "Create a new pipeline",
+ "parameters": [],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipelines": {
+ "get": {
+ "operationId": "PlatformApiController_getPipelines",
+ "summary": "List all pipelines for customer",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/{pipelineId}": {
+ "get": {
+ "operationId": "PlatformApiController_getPipeline",
+ "summary": "Get pipeline by ID",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ },
+ "patch": {
+ "operationId": "PlatformApiController_updatePipeline",
+ "summary": "Update pipeline by ID",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ },
+ "delete": {
+ "operationId": "PlatformApiController_deletePipeline",
+ "summary": "Delete pipeline by ID",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/execute": {
+ "post": {
+ "operationId": "PlatformApiController_executePipeline",
+ "summary": "Execute a pipeline",
+ "parameters": [],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/pause": {
+ "post": {
+ "operationId": "PlatformApiController_pausePipeline",
+ "summary": "Pause a pipeline",
+ "parameters": [],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/unpause": {
+ "post": {
+ "operationId": "PlatformApiController_unpausePipeline",
+ "summary": "Unpause a pipeline",
+ "parameters": [],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/{pipelineId}/memory": {
+ "put": {
+ "operationId": "PlatformApiController_updatePipelineMemory",
+ "summary": "Update pipeline memory configuration",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/{pipelineId}/metadata": {
+ "put": {
+ "operationId": "PlatformApiController_updatePipelineMetadata",
+ "summary": "Update pipeline metadata",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipelines/metadata": {
+ "get": {
+ "operationId": "PlatformApiController_getPipelinesMetadata",
+ "summary": "Get all pipelines metadata",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/pipeline_run": {
+ "post": {
+ "operationId": "PlatformApiController_createPipelineRun",
+ "summary": "Create a pipeline run",
+ "parameters": [],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/{pipelineId}/pipeline_run": {
+ "get": {
+ "operationId": "PlatformApiController_getPipelineRuns",
+ "summary": "Get pipeline runs for a pipeline",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/{pipelineId}/pipeline_run/{runId}": {
+ "get": {
+ "operationId": "PlatformApiController_getPipelineRun",
+ "summary": "Get specific pipeline run",
+ "parameters": [
+ {
+ "name": "pipelineId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "runId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/pipeline/pipeline_run/{runId}/logs": {
+ "get": {
+ "operationId": "PlatformApiController_getPipelineRunLogs",
+ "summary": "Get pipeline run logs",
+ "parameters": [
+ {
+ "name": "runId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/{jobId}/input": {
+ "put": {
+ "operationId": "PlatformApiController_updateJobInput",
+ "summary": "Update job input columns",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ },
+ "patch": {
+ "operationId": "PlatformApiController_patchJobInput",
+ "summary": "Partial update job input columns",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/{jobId}/memory": {
+ "put": {
+ "operationId": "PlatformApiController_updateJobMemory",
+ "summary": "Update job memory configuration",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/{jobId}/reset-state": {
+ "post": {
+ "operationId": "PlatformApiController_resetJobState",
+ "summary": "Reset job state",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/jdbc/{jobId}": {
+ "get": {
+ "operationId": "PlatformApiController_getJdbcJob",
+ "summary": "Get JDBC job details",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/jdbc/{jobId}/sync-mode": {
+ "post": {
+ "operationId": "PlatformApiController_updateJdbcSyncMode",
+ "summary": "Update JDBC job sync mode",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/jdbc/configs/allowed_datatypes": {
+ "get": {
+ "operationId": "PlatformApiController_getJdbcAllowedDatatypes",
+ "summary": "Get allowed datatypes for JDBC",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/singer/{jobId}": {
+ "get": {
+ "operationId": "PlatformApiController_getSingerJob",
+ "summary": "Get Singer job details",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/singer/{jobId}/sync-mode": {
+ "post": {
+ "operationId": "PlatformApiController_updateSingerSyncMode",
+ "summary": "Update Singer job sync mode",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/jobs/s3/{jobId}": {
+ "get": {
+ "operationId": "PlatformApiController_getS3Job",
+ "summary": "Get S3 job details",
+ "parameters": [
+ {
+ "name": "jobId",
+ "required": true,
+ "in": "path",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
+ "/platform/health": {
+ "get": {
+ "operationId": "PlatformApiController_healthCheck",
+ "summary": "Platform API health check",
+ "parameters": [],
+ "responses": {
+ "200": {
+ "description": "",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ "Platform API"
+ ],
+ "security": [
+ {
+ "access-token": []
+ }
+ ]
+ }
+ },
"/health": {
"get": {
"operationId": "HealthController_check",
diff --git a/src/main.ts b/src/main.ts
index 70161e2..fc90db0 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -22,6 +22,7 @@ async function bootstrap() {
logger,
cors: {
origin: [
+ 'http://localhost:4200',
'https://app.stg.dadosfera.ai',
'https://app.dadosfera.ai',
'https://unimed.dadosfera.ai',
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index d9006ef..3be5530 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -49,7 +49,52 @@ export class PlatformApiController {
return id?.replace(/-/g, '_') || '';
}
+ /**
+ * Denormalize ID back to UUID format (replace _ with -).
+ * Used when we receive a normalized ID but need the original UUID.
+ */
+ private denormalizeId(id: string): string {
+ return id?.replace(/_/g, '-') || '';
+ }
+
+ /**
+ * Normalize job ID to match Platform-API format.
+ * Platform-API replaces '-' with '_' in job IDs.
+ *
+ * Example: "2ccf5481-59f5-4036-8a94-7d5f28f4f899-0" -> "2ccf5481_59f5_4036_8a94_7d5f28f4f899_0"
+ */
+ private normalizeJobId(jobId: string): string {
+ return jobId?.replace(/-/g, '_') || '';
+ }
+
+ /**
+ * Extract the pipeline ID (base UUID) from a job ID.
+ * Job IDs have format "uuid-suffix" where suffix is the job index (e.g., "0", "1").
+ * Handles both hyphenated and underscored formats, always returns hyphenated UUID for ES.
+ *
+ * Examples:
+ * - "2ccf5481-59f5-4036-8a94-7d5f28f4f899-0" -> "2ccf5481-59f5-4036-8a94-7d5f28f4f899"
+ * - "2ccf5481_59f5_4036_8a94_7d5f28f4f899_0" -> "2ccf5481-59f5-4036-8a94-7d5f28f4f899"
+ */
+ private extractPipelineIdFromJobId(jobId: string): string {
+ if (!jobId) return '';
+
+ // Determine the separator used in the jobId
+ const hasUnderscores = jobId.includes('_');
+ const separator = hasUnderscores ? '_' : '-';
+
+ const parts = jobId.split(separator);
+ // UUID has 5 parts (8-4-4-4-12), job suffix is the 6th part
+ if (parts.length >= 6) {
+ // Always return hyphenated format for Elasticsearch lookup
+ return parts.slice(0, 5).join('-');
+ }
+ // If no suffix found, return the ID in hyphenated format
+ return hasUnderscores ? jobId.replace(/_/g, '-') : jobId;
+ }
+
private readonly VALID_CONNECTORS = ['jdbc', 'singer', 's3'];
+ private readonly MAX_MEMORY_MB = 12000; // 12GB maximum memory per pipeline/job
/**
* Validate that connector is provided and is a valid type.
@@ -62,6 +107,17 @@ export class PlatformApiController {
}
}
+ /**
+ * Validate memory allocation against maximum limit.
+ */
+ private validateMemory(memoryMb: number): void {
+ if (memoryMb > this.MAX_MEMORY_MB) {
+ throw new BadRequestException(
+ `Memory limit exceeded. Maximum allowed: ${this.MAX_MEMORY_MB}MB (12GB)`,
+ );
+ }
+ }
+
/**
* Validate cron expression against customer's schedule limit.
* Fetches current scheduleLimit from DUC to ensure up-to-date configuration.
@@ -107,7 +163,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: { name: string; type: string };
+ reference_column?: string;
}> {
if (!jobs || jobs.length === 0) return [];
@@ -115,7 +171,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: { name: string; type: string };
+ reference_column?: string;
}> = [];
for (const job of jobs) {
@@ -128,7 +184,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: { name: string; type: string };
+ reference_column?: string;
} = {
name: input.table_name || '',
type: input.load_type || 'full_load',
@@ -137,10 +193,8 @@ export class PlatformApiController {
table.columns = input.column_include_list;
}
if (input.incremental_column_name) {
- table.reference_column = {
- name: input.incremental_column_name,
- type: input.incremental_column_type || 'timestamp',
- };
+ // reference_column is stored as a string (column name)
+ table.reference_column = input.incremental_column_name;
}
tables.push(table);
} else if (connector === 'singer' || connector === 's3') {
@@ -205,6 +259,148 @@ export class PlatformApiController {
return properties;
}
+ /**
+ * Sync job input changes to DynamoDB for a specific connector type.
+ * Extracts pipeline ID from job ID, fetches ES document to find input ID,
+ * then updates the table entry in DynamoDB.
+ *
+ * Job ID transformations:
+ * - Raw format (from endpoint): "2ccf5481-59f5-4036-8a94-7d5f28f4f899-0"
+ * - Platform API format: "2ccf5481_59f5_4036_8a94_7d5f28f4f899_0" (underscores)
+ * - Elasticsearch pipeline ID: "2ccf5481-59f5-4036-8a94-7d5f28f4f899" (UUID only, hyphens)
+ *
+ * @param connectorType - The connector type ('jdbc', 'singer', 's3') for the Platform API endpoint
+ */
+ private async syncJobInputToDynamoDB(
+ jobId: string,
+ body: any,
+ user: RequestUser,
+ connectorType: 'jdbc' | 'singer' | 's3',
+ ): Promise {
+ try {
+ // Normalize job ID for Platform API GET (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
+ // Get job details using connector-specific endpoint to find table_name
+ const jobResult = await this.platformApiService.proxy(
+ 'GET',
+ `/jobs/${connectorType}/${normalizedJobId}`,
+ user,
+ );
+
+ // Extract the pipeline ID (base UUID) from the raw job ID for ES lookup
+ const esPipelineId = this.extractPipelineIdFromJobId(jobId);
+ const tableName = body.table_name || jobResult.source_config?.table_name;
+
+ if (!esPipelineId || !tableName) {
+ this.logger.warn('Cannot sync job input: missing pipeline_id or table_name', {
+ jobId,
+ esPipelineId,
+ tableName,
+ });
+ return;
+ }
+
+ // Get pipeline from ES to find input ID (stored in config.tables)
+ const pipeline = await this.elasticsearchService.getPipeline(
+ user.customer_name,
+ esPipelineId,
+ );
+
+ const inputId = pipeline?.config?.tables;
+ if (!inputId) {
+ this.logger.warn('Cannot sync job input: no input ID in ES', {
+ jobId,
+ esPipelineId,
+ });
+ return;
+ }
+
+ // Build changes for DynamoDB table entry
+ // reference_column is stored as a string (column name), not an object
+ const changes: {
+ type?: string;
+ columns?: string[];
+ reference_column?: string | null;
+ } = {};
+
+
+ if ('target_load_type' in body) {
+ changes.type = body.target_load_type;
+ }
+ if ('column_include_list' in body) {
+ changes.columns = body.column_include_list;
+ }
+ if ('incremental_column_name' in body) {
+ // reference_column is just the column name as a string
+ changes.reference_column = body.incremental_column_name || null;
+ }
+
+ // Update DynamoDB if there are changes
+ if (Object.keys(changes).length > 0) {
+ await this.dynamoDBService.updateInputTable(
+ user.customer_id,
+ inputId,
+ tableName,
+ changes,
+ );
+ }
+ } catch (error) {
+ this.logger.error('Failed to sync job input to DynamoDB', {
+ jobId,
+ connectorType,
+ error: error.message,
+ });
+ // Don't throw - Platform API update succeeded, just log the sync error
+ }
+ }
+
+ /**
+ * Sync sync-mode changes to DynamoDB for JDBC connectors.
+ * Always passes both target_load_type and incremental_column_name to ensure proper sync.
+ */
+ private async syncJdbcSyncModeToDynamoDB(
+ jobId: string,
+ body: any,
+ user: RequestUser,
+ ): Promise {
+ // JDBC sync mode uses target_load_type field
+ const changes: any = {};
+
+ if ('target_load_type' in body) {
+ changes.target_load_type = body.target_load_type;
+ }
+
+ // Handle incremental_column_name:
+ // - If provided in body, use that value
+ // - If changing to full_load, explicitly clear it
+ if ('incremental_column_name' in body) {
+ changes.incremental_column_name = body.incremental_column_name;
+ changes.incremental_column_type = body.incremental_column_type;
+ } else if (body.target_load_type === 'full_load') {
+ // Changing to full_load without specifying incremental_column - clear it
+ changes.incremental_column_name = null;
+ }
+
+ await this.syncJobInputToDynamoDB(jobId, changes, user, 'jdbc');
+ }
+
+ /**
+ * Sync sync-mode changes to DynamoDB for Singer connectors.
+ */
+ private async syncSingerSyncModeToDynamoDB(
+ jobId: string,
+ body: any,
+ user: RequestUser,
+ ): Promise {
+ // Singer sync mode uses replication_method field
+ // Map to DynamoDB type: FULL_TABLE -> full_load, INCREMENTAL -> incremental
+ if ('replication_method' in body) {
+ const type = body.replication_method === 'INCREMENTAL' ? 'incremental' : 'full_load';
+ await this.syncJobInputToDynamoDB(jobId, { load_type: type }, user, 'singer');
+ }
+ }
+
// ==================== PIPELINE ROUTES ====================
@Post('pipeline')
@@ -446,6 +642,11 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
+ // Validate memory limit
+ if (body.amount) {
+ this.validateMemory(body.amount);
+ }
+
return this.platformApiService.proxy(
'PUT',
`/pipeline/${pipelineId}/memory`,
@@ -561,12 +762,23 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
- return this.platformApiService.proxy(
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
+ const result = await this.platformApiService.proxy(
'PUT',
- `/jobs/${jobId}/input`,
+ `/jobs/${normalizedJobId}/input`,
user,
body,
);
+
+ // Sync to DynamoDB if connector type is provided
+ const connectorType = body.connector as 'jdbc' | 'singer' | 's3' | undefined;
+ if (connectorType && this.VALID_CONNECTORS.includes(connectorType)) {
+ await this.syncJobInputToDynamoDB(jobId, body, user, connectorType);
+ }
+
+ return result;
}
@Patch('jobs/:jobId/input')
@@ -577,12 +789,23 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
- return this.platformApiService.proxy(
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
+ const result = await this.platformApiService.proxy(
'PATCH',
- `/jobs/${jobId}/input`,
+ `/jobs/${normalizedJobId}/input`,
user,
body,
);
+
+ // Sync to DynamoDB if connector type is provided
+ const connectorType = body.connector as 'jdbc' | 'singer' | 's3' | undefined;
+ if (connectorType && this.VALID_CONNECTORS.includes(connectorType)) {
+ await this.syncJobInputToDynamoDB(jobId, body, user, connectorType);
+ }
+
+ return result;
}
@Put('jobs/:jobId/memory')
@@ -593,9 +816,17 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
+ // Validate memory limit
+ if (body.amount) {
+ this.validateMemory(body.amount);
+ }
+
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
return this.platformApiService.proxy(
'PUT',
- `/jobs/${jobId}/memory`,
+ `/jobs/${normalizedJobId}/memory`,
user,
body,
);
@@ -609,9 +840,12 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
return this.platformApiService.proxy(
'POST',
- `/jobs/${jobId}/reset-state`,
+ `/jobs/${normalizedJobId}/reset-state`,
user,
body,
);
@@ -623,10 +857,12 @@ export class PlatformApiController {
@ApiOperation({ summary: 'Get JDBC job details' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
async getJdbcJob(@Param('jobId') jobId: string, @User() user: RequestUser) {
- return this.platformApiService.proxy('GET', `/jobs/jdbc/${jobId}`, user);
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+ return this.platformApiService.proxy('GET', `/jobs/jdbc/${normalizedJobId}`, user);
}
- @Put('jobs/jdbc/:jobId/sync-mode')
+ @Post('jobs/jdbc/:jobId/sync-mode')
@ApiOperation({ summary: 'Update JDBC job sync mode' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
async updateJdbcSyncMode(
@@ -634,12 +870,20 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
- return this.platformApiService.proxy(
- 'PUT',
- `/jobs/jdbc/${jobId}/sync-mode`,
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
+ const result = await this.platformApiService.proxy(
+ 'POST',
+ `/jobs/jdbc/${normalizedJobId}/sync-mode`,
user,
body,
);
+
+ // Sync to DynamoDB (pass raw jobId for pipeline extraction)
+ await this.syncJdbcSyncModeToDynamoDB(jobId, body, user);
+
+ return result;
}
@Get('jobs/jdbc/configs/allowed_datatypes')
@@ -659,10 +903,12 @@ export class PlatformApiController {
@ApiOperation({ summary: 'Get Singer job details' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
async getSingerJob(@Param('jobId') jobId: string, @User() user: RequestUser) {
- return this.platformApiService.proxy('GET', `/jobs/singer/${jobId}`, user);
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+ return this.platformApiService.proxy('GET', `/jobs/singer/${normalizedJobId}`, user);
}
- @Put('jobs/singer/:jobId/sync-mode')
+ @Post('jobs/singer/:jobId/sync-mode')
@ApiOperation({ summary: 'Update Singer job sync mode' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
async updateSingerSyncMode(
@@ -670,12 +916,20 @@ export class PlatformApiController {
@Body() body: any,
@User() user: RequestUser,
) {
- return this.platformApiService.proxy(
- 'PUT',
- `/jobs/singer/${jobId}/sync-mode`,
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+
+ const result = await this.platformApiService.proxy(
+ 'POST',
+ `/jobs/singer/${normalizedJobId}/sync-mode`,
user,
body,
);
+
+ // Sync to DynamoDB (pass raw jobId for pipeline extraction)
+ await this.syncSingerSyncModeToDynamoDB(jobId, body, user);
+
+ return result;
}
// ==================== JOBS - S3 ROUTES ====================
@@ -684,7 +938,9 @@ export class PlatformApiController {
@ApiOperation({ summary: 'Get S3 job details' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
async getS3Job(@Param('jobId') jobId: string, @User() user: RequestUser) {
- return this.platformApiService.proxy('GET', `/jobs/s3/${jobId}`, user);
+ // Normalize job ID for Platform API (replace - with _)
+ const normalizedJobId = this.normalizeJobId(jobId);
+ return this.platformApiService.proxy('GET', `/jobs/s3/${normalizedJobId}`, user);
}
// ==================== HEALTH ROUTE ====================
diff --git a/src/services/dynamodb/dynamodb.service.ts b/src/services/dynamodb/dynamodb.service.ts
index aead208..099eb99 100644
--- a/src/services/dynamodb/dynamodb.service.ts
+++ b/src/services/dynamodb/dynamodb.service.ts
@@ -24,7 +24,7 @@ export interface InputDocument {
name: string;
type: string;
columns?: string[];
- reference_column?: { name: string; type: string };
+ reference_column?: string;
}>;
credentials?: Record;
}
@@ -62,7 +62,7 @@ export class DynamoDBService {
name: string;
type: string;
columns?: string[];
- reference_column?: { name: string; type: string };
+ reference_column?: string;
}>;
},
): Promise {
@@ -145,4 +145,85 @@ export class DynamoDBService {
this.logger.info('DynamoDB: Input deleted successfully', { inputId });
}
+
+ /**
+ * Update a specific table entry in the input document.
+ * Fetches the current document, updates the matching table, and saves.
+ */
+ async updateInputTable(
+ clientId: string,
+ inputId: string,
+ tableName: string,
+ changes: {
+ type?: string;
+ columns?: string[];
+ reference_column?: string | null;
+ },
+ ): Promise {
+ const dynamoTableName = DYNAMODB_CONFIG.inputsTable();
+
+ this.logger.info('DynamoDB: Updating input table', {
+ inputId,
+ tableName,
+ changes: Object.keys(changes),
+ });
+
+ // Get current document
+ const current = await this.findInput(clientId, inputId);
+ if (!current) {
+ this.logger.warn('DynamoDB: Input not found for update', { inputId });
+ return;
+ }
+
+ // Find and update the matching table
+ const tables = current.tables || [];
+ const tableIndex = tables.findIndex((t) => t.name === tableName);
+
+ if (tableIndex === -1) {
+ this.logger.warn('DynamoDB: Table not found in input', {
+ inputId,
+ tableName,
+ });
+ return;
+ }
+
+ // Merge changes into the table entry
+ const updatedTable = { ...tables[tableIndex] };
+ if ('type' in changes) updatedTable.type = changes.type;
+ if ('columns' in changes) updatedTable.columns = changes.columns;
+ if ('reference_column' in changes) {
+ if (changes.reference_column === null) {
+ delete updatedTable.reference_column;
+ } else {
+ updatedTable.reference_column = changes.reference_column;
+ }
+ }
+
+ tables[tableIndex] = updatedTable;
+
+ // Save updated document
+ const putCommand = new PutCommand({
+ TableName: dynamoTableName,
+ Item: {
+ ...current,
+ tables,
+ updated_at: new Date().toISOString(),
+ },
+ });
+
+ try {
+ await this.documentClient.send(putCommand);
+ this.logger.info('DynamoDB: Input table updated successfully', {
+ inputId,
+ tableName,
+ });
+ } catch (error) {
+ this.logger.error('DynamoDB: Failed to update input table', {
+ inputId,
+ tableName,
+ error: error.message,
+ });
+ throw error;
+ }
+ }
}
diff --git a/src/services/elasticsearch/elasticsearch.service.ts b/src/services/elasticsearch/elasticsearch.service.ts
index 281b5d6..e2c1857 100644
--- a/src/services/elasticsearch/elasticsearch.service.ts
+++ b/src/services/elasticsearch/elasticsearch.service.ts
@@ -293,6 +293,33 @@ export class ElasticsearchService {
}
}
+ async getPipeline(
+ customerName: string,
+ pipelineId: string,
+ ): Promise {
+ const index = this.getIndex(customerName);
+
+ this.logger.info('Elasticsearch: Getting pipeline', {
+ index,
+ pipelineId,
+ });
+
+ try {
+ const response = await this.client.get(`${index}/_doc/${pipelineId}`);
+ return response.data._source as PipelineDocument;
+ } catch (error) {
+ if (error instanceof AxiosError && error.response?.status === 404) {
+ this.logger.warn('Elasticsearch: Pipeline not found', {
+ pipelineId,
+ index,
+ });
+ return null;
+ }
+ this.handleError('getPipeline', error, { pipelineId, index });
+ throw error;
+ }
+ }
+
async deletePipeline(
customerName: string,
pipelineId: string,
From 0a5e8001f9245c2700aebd0772e143fc7b64d666 Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 16:57:25 -0300
Subject: [PATCH 25/41] UPDATE: adding platform_api_url
---
deploy/helm-chart/templates/deployment.yaml | 2 ++
deploy/helm-chart/values-stg.yaml | 1 +
deploy/helm-chart/values.yaml | 1 +
3 files changed, 4 insertions(+)
diff --git a/deploy/helm-chart/templates/deployment.yaml b/deploy/helm-chart/templates/deployment.yaml
index 63524f3..8614986 100644
--- a/deploy/helm-chart/templates/deployment.yaml
+++ b/deploy/helm-chart/templates/deployment.yaml
@@ -106,6 +106,8 @@ spec:
value: "{{ .Values.maestro.redis_port }}"
- name: REDIS_TLS
value: "{{ .Values.maestro.redis_tls }}"
+ - name: PLATFORM_API_URL
+ value: {{ .Values.maestro.platform_api_url }}
- name: JWT_PRIVATE_KEY
valueFrom:
secretKeyRef:
diff --git a/deploy/helm-chart/values-stg.yaml b/deploy/helm-chart/values-stg.yaml
index 13e2d05..360aafe 100644
--- a/deploy/helm-chart/values-stg.yaml
+++ b/deploy/helm-chart/values-stg.yaml
@@ -8,6 +8,7 @@ maestro:
open_group_id: e3f98a2f-7748-4981-8505-7695c8ca8218
cookie_secret: "ff7bc13823edb2ae50d248e5780bddc9d4b31c36"
redis_database: "1"
+ platform_api_url: https://xs2hkhq07k.execute-api.us-east-1.amazonaws.com
hostname: maestro.stg.dadosfera.ai
diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml
index 2f703b7..30af31e 100644
--- a/deploy/helm-chart/values.yaml
+++ b/deploy/helm-chart/values.yaml
@@ -43,6 +43,7 @@ maestro:
upload_file_agent_connection: cbc2f881-58c4-4d60-8003-0979b0b5b911
open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e
open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9
+ platform_api_url: https://oz8v2zid1e.execute-api.us-east-1.amazonaws.com
dedicated_proxy: ""
restricted_ip: ""
redis_host: "aaapzppmlyamkocqwstpo7zvopczyyiyuy6xzm2g6c5k4mq3a66be4a-0.redis.sa-saopaulo-1.oci.oraclecloud.com"
From bd231382ebf3f5567d7cd38a21c037090e0a7c22 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Tue, 16 Dec 2025 19:58:38 +0000
Subject: [PATCH 26/41] =?UTF-8?q?WIP:=20adiciona=20par=C3=A2metro=20asset?=
=?UTF-8?q?=5Ftype=20no=20docsfera.json?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docsfera.json | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/docsfera.json b/docsfera.json
index 4d80f69..4f1c426 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -4483,6 +4483,14 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "asset_type",
+ "required": true,
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
From fc9c0b09910238b4bc6df67e47df0f4079465148 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Tue, 16 Dec 2025 19:54:03 +0000
Subject: [PATCH 27/41] WIP: Filtro Source - backend
---
src/modules/catalog/catalog.service.ts | 304 +++++++++++++------------
1 file changed, 153 insertions(+), 151 deletions(-)
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index c56313e..7660cd6 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -41,7 +41,6 @@ import {
import { TypeParser } from 'src/utils/FileParser/parser-types';
import { ParserBuilder } from 'src/utils/FileParser/parser.builder';
-
class CatalogService implements OnModuleInit {
catalogReadService: ReadService.CatalogReadServices;
catalogWriteService: WriteService.CatalogWriteServices;
@@ -58,7 +57,6 @@ class CatalogService implements OnModuleInit {
this.logger = dadosferaLogger.logger;
}
-
onModuleInit() {
this.catalogReadService =
this.grpcClient.getService(
@@ -74,81 +72,65 @@ class CatalogService implements OnModuleInit {
);
}
-
_getNimbusUrl(body) {
this.logger.debug(`Body: ${JSON.stringify(body)}`);
const customer = body.info.customer.toLowerCase();
-
if (process.env.ENV === 'prd') {
return `https://nimbus-${customer}.dadosfera.ai`;
}
-
return `https://nimbus-${customer}.${process.env.ENV.replace(
'local',
'stg',
)}.dadosfera.ai`;
}
-
async getPiiReporter(metadata: Metadata, type: TypeParser) {
- this.logger.info('getPiiReporter: ' + type)
+ this.logger.info('getPiiReporter: ' + type);
try {
- const {
- data
- } = await lastValueFrom(
- this.catalogWriteService.GetPiiReporter({}, metadata)
- )
- this.logger.info("Finish grpc call")
-
+ const { data } = await lastValueFrom(
+ this.catalogWriteService.GetPiiReporter({}, metadata),
+ );
+ this.logger.info('Finish grpc call');
const parser = ParserBuilder.build(type);
-
- this.logger.info('parser file to: ' + type)
- const file = await parser.parse(data)
- this.logger.info('finish parser')
+ this.logger.info('parser file to: ' + type);
+ const file = await parser.parse(data);
+ this.logger.info('finish parser');
const mimeTypes: Record = {
- 'csv': 'text/csv',
- 'html': 'text/html',
- 'pdf': 'application/pdf'
- }
-
+ csv: 'text/csv',
+ html: 'text/html',
+ pdf: 'application/pdf',
+ };
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `relatorio-pii-${timestamp}.${type}`;
-
return {
file,
filename: filename,
- type: mimeTypes[type]
- }
+ type: mimeTypes[type],
+ };
} catch (error) {
this.logger.error(error.message);
throw error;
}
-
-
}
-
async createDataAsset(data: Messages.CreateDataAssetRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
if (!data.embed) data.embed = undefined;
-
return lastValueFrom(
this.catalogWriteService.CreateDataAsset(data, metadata),
);
}
-
async managePermissions(data: Messages.ManagePermissionRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
-
return lastValueFrom(
this.catalogWriteService.ManagePermission(data, metadata),
).catch((err) => {
@@ -159,11 +141,9 @@ class CatalogService implements OnModuleInit {
});
}
-
async revokePermissions(data: Messages.RevokePermissionRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
-
return lastValueFrom(
this.catalogWriteService.RevokePermission(data, metadata),
).catch((err) => {
@@ -174,11 +154,9 @@ class CatalogService implements OnModuleInit {
});
}
-
async commentOnDataAsset(data: Messages.MakeACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
-
return lastValueFrom(
this.catalogWriteService.MakeAComment(data, metadata),
).catch((err) => {
@@ -189,11 +167,9 @@ class CatalogService implements OnModuleInit {
});
}
-
async deleteComment(data: Messages.UpdateACommentRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
-
return lastValueFrom(
this.catalogWriteService.UpdateAComment(data, metadata),
).catch((err) => {
@@ -204,11 +180,9 @@ class CatalogService implements OnModuleInit {
});
}
-
async deleteDataAsset(data: Messages.DeleteDataAssetRequest, metadata) {
this.logger.info('CatalogService - Manage Data assets permissions');
-
return lastValueFrom(
this.catalogWriteService.DeleteDataAsset(data, metadata),
).catch((err) => {
@@ -219,61 +193,110 @@ class CatalogService implements OnModuleInit {
});
}
-
async getUserRolesIds(userId: string) {
const result = await this.userService.findOneById(userId).catch(() => null);
-
if (result) {
return result.user.roles.map((role) => role.id);
}
-
return [];
}
-
async searchDataAssets(
query: Record,
metadata: Metadata,
customer_id: string,
) {
- this.logger.info('CatalogService - searchDataAssets');
+ this.logger.info('CatalogService - searchDataAssets', { query });
- const { search, page, size, sort_by, order, owner, ...filters } = query;
-
- // Verificar se filters.owner existe
- if (owner !== undefined && owner !== null) {
+ const { search, page, size, sort_by, order, ...filters } = query;
+
+ this.logger.debug('Extracted filters:', { filters });
+
+ console.log('MAESTRO VAI CHAMAR PI-FACTORY COM (ANTES AJUSTE):', {
+ search,
+ page,
+ size,
+ sort_by,
+ order,
+ filters,
+ });
+
+ // 🔥 AJUSTE DO manually AQUI: converte '1'/'0' string em número ou remove
+ if (
+ filters.manually !== undefined &&
+ filters.manually !== null &&
+ filters.manually !== ''
+ ) {
+ filters.manually = Number(filters.manually); // 1 ou 0
+ } else {
+ delete filters.manually;
+ }
+
+ console.log('MAESTRO VAI CHAMAR PI-FACTORY COM (DEPOIS AJUSTE):', {
+ search,
+ page,
+ size,
+ sort_by,
+ order,
+ filters,
+ });
+
+ if (filters.owner) {
const { users: customer_users } =
await this.userService.findAllUsersByCustomerId(customer_id);
- let ownerValues: string[];
- if (Array.isArray(owner)) {
- ownerValues = owner;
- } else if (typeof owner === 'string' && owner.includes(',')) {
- ownerValues = owner.split(',').map((o: string) => o.trim());
- } else {
- ownerValues = [owner];
- }
-
- // Separar "sem owner" (marcador especial null) dos owners normais
- const hasEmptyOwner = ownerValues.some(v => v === 'null');
- const normalOwners = ownerValues.filter(v => v !== 'null');
-
- // Converter nomes de owners para IDs
- const ownerIds = normalOwners.map((ownerValue: string) => {
- const user = customer_users.find(u =>
- u.name === ownerValue || u.email === ownerValue || u.id === ownerValue
- );
- return user ? user.id : ownerValue;
+ this.logger.info('Available users in database count:', {
+ count: customer_users.length,
+ });
+ this.logger.info('First 5 users:', {
+ users: customer_users
+ .slice(0, 5)
+ .map((u) => ({ id: u.id, email: u.email, name: u.name })),
});
- // Se tiver "sem owner", adicionar marcador especial
- if (hasEmptyOwner) {
- ownerIds.push('null');
- }
+ const ownerValues = Array.isArray(filters.owner)
+ ? filters.owner
+ : typeof filters.owner === 'string' && filters.owner.includes(',')
+ ? filters.owner.split(',').map((o: string) => o.trim())
+ : [filters.owner];
+
+ this.logger.info('Owner values to convert:', {
+ ownerValues,
+ ownerFiltersOriginal: filters.owner,
+ });
+
+ const ownerIds = ownerValues
+ .map((ownerValue: string) => {
+ const normalizedOwner = ownerValue.replace(/\s/g, '+');
+ const user = customer_users.find((u) => {
+ const isIdMatch = u.id === ownerValue;
+ const isEmailMatch =
+ u.email === ownerValue || u.email === normalizedOwner;
+ const isNameMatch =
+ u.name === ownerValue || u.name === normalizedOwner;
+ this.logger.info('Comparing:', {
+ userId: u.id,
+ userEmail: u.email,
+ userName: u.name,
+ filterValue: ownerValue,
+ normalizedFilter: normalizedOwner,
+ idMatch: isIdMatch,
+ emailMatch: isEmailMatch,
+ nameMatch: isNameMatch,
+ });
+ return isIdMatch || isEmailMatch || isNameMatch;
+ });
+ this.logger.info('Looking for owner result:', {
+ ownerValue,
+ found: !!user,
+ userId: user?.id,
+ });
+ return user?.id || ownerValue;
+ })
+ .filter((id: string) => id);
- // Adicionar ao filters apenas se houver valores
if (ownerIds.length > 0) {
filters.owner = ownerIds;
}
@@ -293,20 +316,18 @@ class CatalogService implements OnModuleInit {
),
);
+ console.log('MAESTRO RECEBEU RESPOSTA DO PI-FACTORY');
const result = JSON.parse(data_assets);
-
const response = await this.getAssetsUsersAndRoles(
result.data_assets,
customer_id,
);
-
return { data_assets: response, total };
}
-
async downloadAssets(
query: Record,
metadata: Metadata,
@@ -314,33 +335,27 @@ class CatalogService implements OnModuleInit {
) {
const data = await this.searchDataAssets(query, metadata, customer_id);
-
- const formatData = data.data_assets.map(asset => ({
+ const formatData = data.data_assets.map((asset) => ({
id: asset.id,
display_name: asset.display_name,
data_asset_type: asset.data_asset_type,
created_at: asset.created_at,
- tags: '[' + asset.tags.join(', ') + ']'
- }))
-
+ tags: '[' + asset.tags.join(', ') + ']',
+ }));
const parser = ParserBuilder.build('csv');
-
const file = await parser.parse(formatData);
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `dadosfera_assets_${timestamp}.csv`;
-
return {
file,
- filename
- }
+ filename,
+ };
}
-
async getOneDataAsset(data: {
id: string;
customer_id: string;
@@ -361,11 +376,9 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
-
return { data_asset: asset[0] };
}
-
async getOneDataAssetByPipelineAndObject(data: {
customer_id: string;
pipeline: string;
@@ -387,11 +400,9 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
-
return { data_asset: asset[0] };
}
-
async updateOneDataAsset(data: {
data_asset_id: string;
customer_id: string;
@@ -400,7 +411,6 @@ class CatalogService implements OnModuleInit {
}) {
const { body, customer_id, data_asset_id, metadata } = data;
-
const { data_asset } = await lastValueFrom(
this.catalogWriteService.UpdateDataAsset(
{ id: data_asset_id, changes: JSON.stringify(body) },
@@ -415,7 +425,6 @@ class CatalogService implements OnModuleInit {
};
asset = await this.getAssetsUsersAndRoles([asset], customer_id);
-
return { data_asset: asset[0] };
}
@@ -423,12 +432,11 @@ class CatalogService implements OnModuleInit {
const { documentation } = await lastValueFrom(
this.catalogReadService.GetDatasetDoc({ id }, metadata),
);
-
+
const docs = JSON.parse(documentation);
return docs;
}
-
async getDatasetPreview(id: string, metadata: Metadata) {
const { preview } = await lastValueFrom(
this.catalogReadService.GetDatasetPreview(
@@ -440,7 +448,6 @@ class CatalogService implements OnModuleInit {
return result;
}
-
async getDatasetColumnsMetadata(id: string, metadata: Metadata) {
const { columns_metadata } = await lastValueFrom(
this.catalogReadService.GetDatasetColumnsMetadata(
@@ -456,7 +463,7 @@ class CatalogService implements OnModuleInit {
if (body.asset_type === 'table' || body.asset_type === 'view') {
return this.createDataDocsViaNimbus(body);
}
-
+
return this.createDataDocsViaGrpc(body, metadata);
}
@@ -470,7 +477,6 @@ class CatalogService implements OnModuleInit {
return data;
}
-
private async createDataDocsViaGrpc(body: CreateDataDocsDTO, metadata: Metadata) {
this.logger.info('Creating data docs via gRPC for other asset types');
try {
@@ -483,9 +489,8 @@ class CatalogService implements OnModuleInit {
metadata,
),
);
-
+
return response;
-
} catch (error) {
this.logger.error('Error creating data asset docs:', error);
throw new HttpException(
@@ -498,7 +503,6 @@ class CatalogService implements OnModuleInit {
async findAllTags(data, metadata) {
this.logger.info('CatalogService - findAllCustomerTags');
-
const response = await lastValueFrom(
this.catalogReadService.GetCustomerTags(data, metadata),
)
@@ -511,9 +515,9 @@ class CatalogService implements OnModuleInit {
throw new Error(err);
});
-
return response;
}
+
async getAssetsUsersAndRoles(data_assets: Array, customer_id: string) {
const { users: customer_users } =
await this.userService.findAllUsersByCustomerId(customer_id);
@@ -526,17 +530,15 @@ class CatalogService implements OnModuleInit {
(u) => u.id === data_asset.owner,
)?.email;
-
const roles = [];
const users = [];
- const data_asset_roles = data_asset?.roles || []
+ const data_asset_roles = data_asset?.roles || [];
for (const role_id of data_asset_roles) {
const role = customer_roles.find((r) => r.id === role_id);
if (role) roles.push({ id: role.id, name: role.name });
}
-
- const data_asset_users = data_asset?.users || []
+ const data_asset_users = data_asset?.users || [];
for (const user_id of data_asset_users) {
const user = customer_users.find((r) => r.id === user_id);
if (user) users.push({ id: user.id, email: user.email });
@@ -550,7 +552,6 @@ class CatalogService implements OnModuleInit {
});
}
-
async triggerCatalog(data: TriggerCatalogReq, metadata: Metadata) {
const { session } = await lastValueFrom(
this.catalogWriteService.TriggerDatasetCataloging(data, metadata),
@@ -564,7 +565,6 @@ class CatalogService implements OnModuleInit {
return res;
}
-
async addRlsRule(data: AddRlsRuleRequest, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogWriteService.AddRlsRule(data, metadata),
@@ -572,7 +572,6 @@ class CatalogService implements OnModuleInit {
return res;
}
-
async removeRlsRule(id: number, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogWriteService.RemoveRlsRule({ id }, metadata),
@@ -580,14 +579,12 @@ class CatalogService implements OnModuleInit {
return res;
}
-
async batchRemoveRlsRule(
query: BatchRemoveRlsRulesRequest,
metadata: Metadata,
) {
const { id_rls, nimbus_dashboard_id } = query;
-
if (id_rls && nimbus_dashboard_id) {
throw new BadRequestException(
"You can't delete using both parameters. Choose either 'id_rls' or 'nimbus_dashboard_id'",
@@ -608,7 +605,6 @@ class CatalogService implements OnModuleInit {
return 'OK';
}
-
async getRlsRules(data: GetRlsRulesRequest, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogReadService.GetRlsRules(data, metadata),
@@ -616,7 +612,6 @@ class CatalogService implements OnModuleInit {
return res.rls_rules;
}
-
async getOneRlsRule(id: number, metadata: Metadata) {
const res = await lastValueFrom(
this.catalogReadService.GetOneRlsRule({ id }, metadata),
@@ -624,7 +619,6 @@ class CatalogService implements OnModuleInit {
return res.rls_rule;
}
-
async getNimbusDashboards(
data: GetNimbusDashboardsRequest,
metadata: Metadata,
@@ -635,88 +629,99 @@ class CatalogService implements OnModuleInit {
return res.dashboards;
}
-
async createTableMetadata(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
- this.logger.info(`Nimbus URL: ${nimbusUrl}`, {...body.logMetadata});
-
+ this.logger.info(`Nimbus URL: ${nimbusUrl}`, { ...body.logMetadata });
const endpoint = `${nimbusUrl}/api/catalog/table-metadata/`;
-
- this.logger.info(`Creating table metadata for table ${body.table_metadata.table_name}`, {...body.logMetadata});
- this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
- this.logger.debug(`Payload: ${JSON.stringify(body.table_metadata)}`, {...body.logMetadata});
-
+ this.logger.info(
+ `Creating table metadata for table ${body.table_metadata.table_name}`,
+ { ...body.logMetadata },
+ );
+ this.logger.info(`Using endpoint: ${endpoint}`, { ...body.logMetadata });
+ this.logger.debug(`Payload: ${JSON.stringify(body.table_metadata)}`, {
+ ...body.logMetadata,
+ });
try {
- const { data, status } = await axios.post(endpoint, {...body.table_metadata});
-
+ const { data, status } = await axios.post(endpoint, {
+ ...body.table_metadata,
+ });
this.logger.info(
`Table metadata created successfully with status ${status} for table ${body.table_metadata.table_name}`,
- {...body.logMetadata},
+ { ...body.logMetadata },
);
return data.id;
} catch (error) {
this.logger.error(
`Failed to create table metadata for table ${body.table_metadata.table_name} failed with status ${
error.response?.status
- } because of ${JSON.stringify(error.response?.data) || error.message}`, {...body.logMetadata});
+ } because of ${JSON.stringify(error.response?.data) || error.message}`,
+ { ...body.logMetadata },
+ );
throw new Error(error.response?.data?.message || error.message);
}
}
-
async createColumnMetadata(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
this.logger.info(`Nimbus URL: ${nimbusUrl}`, body.logMetadata);
const endpoint = `${nimbusUrl}/api/catalog/column-metadata/`;
-
-
-
-
try {
- this.logger.info(`Creating column metadata for table ${body.column_metadata.table_name}`, {...body.logMetadata});
- this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
- this.logger.debug(`Payload: ${JSON.stringify(body.column_metadata)}`, {...body.logMetadata});
- const { data, status } = await axios.post(endpoint, body.column_metadata);
-
+ this.logger.info(
+ `Creating column metadata for table ${body.column_metadata.table_name}`,
+ { ...body.logMetadata },
+ );
+ this.logger.info(`Using endpoint: ${endpoint}`, { ...body.logMetadata });
+ this.logger.debug(
+ `Payload: ${JSON.stringify(body.column_metadata)}`,
+ { ...body.logMetadata },
+ );
+ const { data, status } = await axios.post(
+ endpoint,
+ body.column_metadata,
+ );
this.logger.info(
`Column metadata created successfully with status ${status} for table ${body.column_metadata.table_name}`,
- {...body.logMetadata},
+ { ...body.logMetadata },
);
return data.map((column) => column.id);
} catch (error) {
this.logger.error(
`Failed to create column metadata failed with status for table ${body.column_metadata.table_name} ${
error.response?.status
- } because of ${error.response?.data || error.message}`, {...body.logMetadata});
+ } because of ${error.response?.data || error.message}`,
+ { ...body.logMetadata },
+ );
throw new Error(error.response?.data?.message || error.message);
}
}
-
async createDataPreview(body: any): Promise {
const nimbusUrl = this._getNimbusUrl(body);
- this.logger.info(`Nimbus URL: ${nimbusUrl}`, {...body.logMetadata});
+ this.logger.info(`Nimbus URL: ${nimbusUrl}`, { ...body.logMetadata });
const endpoint = `${nimbusUrl}/api/catalog/data-preview/`;
-
- this.logger.info(`Creating data preview for table ${body.data_preview.table_name}`, {...body.logMetadata});
- this.logger.info(`Using endpoint: ${endpoint}`, {...body.logMetadata});
- this.logger.debug(`Payload: ${JSON.stringify(body.data_preview)}`, {...body.logMetadata});
-
+ this.logger.info(
+ `Creating data preview for table ${body.data_preview.table_name}`,
+ { ...body.logMetadata },
+ );
+ this.logger.info(`Using endpoint: ${endpoint}`, { ...body.logMetadata });
+ this.logger.debug(
+ `Payload: ${JSON.stringify(body.data_preview)}`,
+ { ...body.logMetadata },
+ );
try {
const { data, status } = await axios.post(endpoint, body.data_preview);
-
this.logger.info(
`Data preview created successfully with status ${status} for table ${body.data_preview.table_name}`,
- {...body.logMetadata},
+ { ...body.logMetadata },
);
return data.id;
} catch (error) {
@@ -724,17 +729,15 @@ class CatalogService implements OnModuleInit {
`Failed to create data preview for table ${body.data_preview.table_name} failed with status ${
error.response?.status
} because of ${error.response?.data || error.message}`,
- {...body.logMetadata},
+ { ...body.logMetadata },
);
throw new Error(error.response?.data?.message || error.message);
}
}
-
async catalogDatasetItem(table_metadata_id: number, metadata: Metadata) {
const customer_name_raw = metadata.get('customer_name');
-
const customer_name = customer_name_raw?.[0]?.toString();
if (!customer_name) {
throw new BadRequestException('Customer name not found in metadata');
@@ -757,5 +760,4 @@ class CatalogService implements OnModuleInit {
}
}
-
export { CatalogService };
From ea44a1cbb681117940acfcfba8bc311c6837e078 Mon Sep 17 00:00:00 2001
From: Rafael Moraes
Date: Tue, 16 Dec 2025 20:52:28 +0000
Subject: [PATCH 28/41] FEAT: Manual/Auto filter and UX Adjusments
---
src/modules/catalog/catalog.service.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts
index 7660cd6..89dcf84 100644
--- a/src/modules/catalog/catalog.service.ts
+++ b/src/modules/catalog/catalog.service.ts
@@ -223,7 +223,6 @@ class CatalogService implements OnModuleInit {
filters,
});
- // 🔥 AJUSTE DO manually AQUI: converte '1'/'0' string em número ou remove
if (
filters.manually !== undefined &&
filters.manually !== null &&
From 2cc8f46418fdb4630da01acc2ec60d3faef17e0b Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 18:10:38 -0300
Subject: [PATCH 29/41] feat: add Elasticsearch access to Maestro deployment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add ELASTICSEARCH_URL and ELASTICSEARCH_API_KEY env vars
- Pull credentials from {env}/microservices/elasticsearch secret
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
deploy/helm-chart/templates/deployment.yaml | 11 +++++++++++
deploy/helm-chart/templates/secret.yaml | 12 ++++++++++++
2 files changed, 23 insertions(+)
diff --git a/deploy/helm-chart/templates/deployment.yaml b/deploy/helm-chart/templates/deployment.yaml
index 8614986..7312b30 100644
--- a/deploy/helm-chart/templates/deployment.yaml
+++ b/deploy/helm-chart/templates/deployment.yaml
@@ -128,3 +128,14 @@ spec:
secretKeyRef:
name: prd-{{ .Values.app_name }}
key: AWS_DEFAULT_REGION
+ # Elasticsearch
+ - name: ELASTICSEARCH_URL
+ valueFrom:
+ secretKeyRef:
+ name: prd-{{ .Values.app_name }}
+ key: ELASTICSEARCH_URL
+ - name: ELASTICSEARCH_API_KEY
+ valueFrom:
+ secretKeyRef:
+ name: prd-{{ .Values.app_name }}
+ key: ELASTICSEARCH_API_KEY
diff --git a/deploy/helm-chart/templates/secret.yaml b/deploy/helm-chart/templates/secret.yaml
index 3bbf5ec..10ea9b7 100644
--- a/deploy/helm-chart/templates/secret.yaml
+++ b/deploy/helm-chart/templates/secret.yaml
@@ -38,3 +38,15 @@ spec:
version: "AWSCURRENT"
property: token
+ - secretKey: ELASTICSEARCH_URL
+ remoteRef:
+ key: {{ .Values.maestro.env }}/microservices/elasticsearch
+ version: "AWSCURRENT"
+ property: ELASTICSEARCH_URL
+
+ - secretKey: ELASTICSEARCH_API_KEY
+ remoteRef:
+ key: {{ .Values.maestro.env }}/microservices/elasticsearch
+ version: "AWSCURRENT"
+ property: ELASTICSEARCH_API_KEY
+
From e03b9e7a140819e0113476ff2b4fd4c27fe2ac13 Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 18:23:19 -0300
Subject: [PATCH 30/41] UPDATE: force deployment
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index 4d4a5b1..bb50d3a 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
-
# Maestro
Maestro é a API principal da Dadosfera. É responsável pela comunicação do Frontend com nossos microsserviços.
From e616061c211f7afb57de5e11fb053d2668234e3d Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 19:10:23 -0300
Subject: [PATCH 31/41] fix: normalize IDs in pipeline run routes before
calling Platform API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add normalization for pipelineId and runId in getPipelineRuns, getPipelineRun, and getPipelineRunLogs
- Remove unused createPipelineRun route
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
.../platform-api/platform-api.controller.ts | 22 ++++++-------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 3be5530..1f1fc98 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -691,18 +691,6 @@ export class PlatformApiController {
// ==================== PIPELINE RUN ROUTES ====================
- @Post('pipeline/pipeline_run')
- @ApiOperation({ summary: 'Create a pipeline run' })
- @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
- async createPipelineRun(@Body() body: any, @User() user: RequestUser) {
- return this.platformApiService.proxy(
- 'POST',
- '/pipeline/pipeline_run',
- user,
- body,
- );
- }
-
@Get('pipeline/:pipelineId/pipeline_run')
@ApiOperation({ summary: 'Get pipeline runs for a pipeline' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET)
@@ -711,9 +699,10 @@ export class PlatformApiController {
@User() user: RequestUser,
@Query() query: Record,
) {
+ const normalizedId = this.normalizePipelineId(pipelineId);
return this.platformApiService.proxy(
'GET',
- `/pipeline/${pipelineId}/pipeline_run`,
+ `/pipeline/${normalizedId}/pipeline_run`,
user,
undefined,
query,
@@ -728,9 +717,11 @@ export class PlatformApiController {
@Param('runId') runId: string,
@User() user: RequestUser,
) {
+ const normalizedPipelineId = this.normalizePipelineId(pipelineId);
+ const normalizedRunId = this.normalizePipelineId(runId);
return this.platformApiService.proxy(
'GET',
- `/pipeline/${pipelineId}/pipeline_run/${runId}`,
+ `/pipeline/${normalizedPipelineId}/pipeline_run/${normalizedRunId}`,
user,
);
}
@@ -743,9 +734,10 @@ export class PlatformApiController {
@User() user: RequestUser,
@Query() query: Record,
) {
+ const normalizedRunId = this.normalizePipelineId(runId);
return this.platformApiService.proxy(
'GET',
- `/pipeline/pipeline_run/${runId}/logs`,
+ `/pipeline/pipeline_run/${normalizedRunId}/logs`,
user,
undefined,
query,
From acb631e33dc342e4c6dce4a2fa08628f0196a69b Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 19:16:35 -0300
Subject: [PATCH 32/41] UPDATE: force deployment
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index bb50d3a..028ca81 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
-
# Maestro
Maestro é a API principal da Dadosfera. É responsável pela comunicação do Frontend com nossos microsserviços.
From 865140e6819ecc1c445b26f747114df4961d8a47 Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 21:05:21 -0300
Subject: [PATCH 33/41] fix: pass type field to Elasticsearch createPipeline
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The type field was missing from the createPipeline call,
causing ES documents to not have the type field set.
Maps: jdbc->database, singer->application, s3->file
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
src/modules/platform-api/platform-api.controller.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 1f1fc98..383647c 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -490,6 +490,7 @@ export class PlatformApiController {
cron: body.cron,
tables: inputId,
properties,
+ type: this.mapConnectorToDynamoType(connectorType),
},
connector,
);
From fb521f53cda74f410e0ed404099b8eb85e2613fd Mon Sep 17 00:00:00 2001
From: Rafael
Date: Tue, 16 Dec 2025 21:05:21 -0300
Subject: [PATCH 34/41] FIX: pass type field to Elasticsearch createPipeline
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The type field was missing from the createPipeline call,
causing ES documents to not have the type field set.
Maps: jdbc->database, singer->application, s3->file
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
src/modules/platform-api/platform-api.controller.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 1f1fc98..383647c 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -490,6 +490,7 @@ export class PlatformApiController {
cron: body.cron,
tables: inputId,
properties,
+ type: this.mapConnectorToDynamoType(connectorType),
},
connector,
);
From e99306adbaf1ce303802e5f4cdf912ead41467fc Mon Sep 17 00:00:00 2001
From: Rafael
Date: Wed, 17 Dec 2025 13:45:18 -0300
Subject: [PATCH 35/41] fix: store reference_column as object with name and
type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The protobuf definition expects reference_column to be an object with
name and type fields, but it was being stored as just a string (column
name). This caused pipeline fetching to fail with the error:
".NewTable.reference_column: object expected"
Changes:
- Update ReferenceColumn interface in DynamoDB service
- Update extractTablesFromJobs to create reference_column object
- Update syncJobInputToDynamoDB to handle reference_column object
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
.../platform-api/platform-api.controller.ts | 38 ++++++++++++-------
src/services/dynamodb/dynamodb.service.ts | 11 ++++--
2 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 383647c..78b273e 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -22,7 +22,7 @@ import { User, RequestUser } from '../../decorators/user.decorator';
import { PlatformApiService } from './platform-api.service';
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
import { ElasticsearchService } from '../../services/elasticsearch';
-import { DynamoDBService } from '../../services/dynamodb';
+import { DynamoDBService, ReferenceColumn } from '../../services/dynamodb';
import { CustomersService } from '../customers/customers.service';
import { validateCronAgainstScheduleLimit } from '../../utils/cron-validation';
@@ -155,7 +155,7 @@ export class PlatformApiController {
* Extract and transform tables from jobs for DynamoDB input.
* Maps connector-specific fields to a common table format.
*
- * - JDBC: load_type, table_name, column_include_list (columns), incremental_column_name (reference_column)
+ * - JDBC: load_type, table_name, column_include_list (columns), incremental_column_name/type (reference_column object)
* - Singer: type maps replication_method (FULL_TABLE -> full_load, INCREMENTAL -> incremental), no columns
* - S3: same mapping as Singer, no columns
*/
@@ -163,7 +163,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}> {
if (!jobs || jobs.length === 0) return [];
@@ -171,7 +171,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}> = [];
for (const job of jobs) {
@@ -179,12 +179,12 @@ export class PlatformApiController {
if (!input) continue;
if (connector === 'jdbc') {
- // JDBC: table_name, load_type, column_include_list, incremental_column_name
+ // JDBC: table_name, load_type, column_include_list, incremental_column_name/type
const table: {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
} = {
name: input.table_name || '',
type: input.load_type || 'full_load',
@@ -193,8 +193,11 @@ export class PlatformApiController {
table.columns = input.column_include_list;
}
if (input.incremental_column_name) {
- // reference_column is stored as a string (column name)
- table.reference_column = input.incremental_column_name;
+ // reference_column is stored as an object with name and type
+ table.reference_column = {
+ name: input.incremental_column_name,
+ type: input.incremental_column_type || 'unknown',
+ };
}
tables.push(table);
} else if (connector === 'singer' || connector === 's3') {
@@ -317,11 +320,11 @@ export class PlatformApiController {
}
// Build changes for DynamoDB table entry
- // reference_column is stored as a string (column name), not an object
+ // reference_column is stored as an object with name and type
const changes: {
type?: string;
columns?: string[];
- reference_column?: string | null;
+ reference_column?: ReferenceColumn | null;
} = {};
@@ -332,8 +335,15 @@ export class PlatformApiController {
changes.columns = body.column_include_list;
}
if ('incremental_column_name' in body) {
- // reference_column is just the column name as a string
- changes.reference_column = body.incremental_column_name || null;
+ // reference_column is stored as an object with name and type
+ if (body.incremental_column_name) {
+ changes.reference_column = {
+ name: body.incremental_column_name,
+ type: body.incremental_column_type || 'unknown',
+ };
+ } else {
+ changes.reference_column = null;
+ }
}
// Update DynamoDB if there are changes
@@ -466,11 +476,13 @@ export class PlatformApiController {
});
}
+ const pipelineType = this.mapConnectorToDynamoType(connectorType);
this.logger.info('Syncing pipeline to Elasticsearch', {
customerName: user.customer_name,
pipelineId: body.id,
plugin,
connector: connectorType,
+ type: pipelineType,
properties,
inputId,
});
@@ -490,7 +502,7 @@ export class PlatformApiController {
cron: body.cron,
tables: inputId,
properties,
- type: this.mapConnectorToDynamoType(connectorType),
+ type: pipelineType,
},
connector,
);
diff --git a/src/services/dynamodb/dynamodb.service.ts b/src/services/dynamodb/dynamodb.service.ts
index 099eb99..15dde41 100644
--- a/src/services/dynamodb/dynamodb.service.ts
+++ b/src/services/dynamodb/dynamodb.service.ts
@@ -11,6 +11,11 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { v4 as uuid } from 'uuid';
import { DYNAMODB_CONFIG } from './dynamodb.config';
+export interface ReferenceColumn {
+ name: string;
+ type: string;
+}
+
export interface InputDocument {
id: string;
client_id: string;
@@ -24,7 +29,7 @@ export interface InputDocument {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}>;
credentials?: Record;
}
@@ -62,7 +67,7 @@ export class DynamoDBService {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}>;
},
): Promise {
@@ -157,7 +162,7 @@ export class DynamoDBService {
changes: {
type?: string;
columns?: string[];
- reference_column?: string | null;
+ reference_column?: ReferenceColumn | null;
},
): Promise {
const dynamoTableName = DYNAMODB_CONFIG.inputsTable();
From 9c55c222309d401195cf75b746a9c28d3f13d36c Mon Sep 17 00:00:00 2001
From: Rafael
Date: Wed, 17 Dec 2025 13:45:18 -0300
Subject: [PATCH 36/41] FIX: store reference_column as object with name and
type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The protobuf definition expects reference_column to be an object with
name and type fields, but it was being stored as just a string (column
name). This caused pipeline fetching to fail with the error:
".NewTable.reference_column: object expected"
Changes:
- Update ReferenceColumn interface in DynamoDB service
- Update extractTablesFromJobs to create reference_column object
- Update syncJobInputToDynamoDB to handle reference_column object
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
.../platform-api/platform-api.controller.ts | 38 ++++++++++++-------
src/services/dynamodb/dynamodb.service.ts | 11 ++++--
2 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 383647c..78b273e 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -22,7 +22,7 @@ import { User, RequestUser } from '../../decorators/user.decorator';
import { PlatformApiService } from './platform-api.service';
import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum';
import { ElasticsearchService } from '../../services/elasticsearch';
-import { DynamoDBService } from '../../services/dynamodb';
+import { DynamoDBService, ReferenceColumn } from '../../services/dynamodb';
import { CustomersService } from '../customers/customers.service';
import { validateCronAgainstScheduleLimit } from '../../utils/cron-validation';
@@ -155,7 +155,7 @@ export class PlatformApiController {
* Extract and transform tables from jobs for DynamoDB input.
* Maps connector-specific fields to a common table format.
*
- * - JDBC: load_type, table_name, column_include_list (columns), incremental_column_name (reference_column)
+ * - JDBC: load_type, table_name, column_include_list (columns), incremental_column_name/type (reference_column object)
* - Singer: type maps replication_method (FULL_TABLE -> full_load, INCREMENTAL -> incremental), no columns
* - S3: same mapping as Singer, no columns
*/
@@ -163,7 +163,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}> {
if (!jobs || jobs.length === 0) return [];
@@ -171,7 +171,7 @@ export class PlatformApiController {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}> = [];
for (const job of jobs) {
@@ -179,12 +179,12 @@ export class PlatformApiController {
if (!input) continue;
if (connector === 'jdbc') {
- // JDBC: table_name, load_type, column_include_list, incremental_column_name
+ // JDBC: table_name, load_type, column_include_list, incremental_column_name/type
const table: {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
} = {
name: input.table_name || '',
type: input.load_type || 'full_load',
@@ -193,8 +193,11 @@ export class PlatformApiController {
table.columns = input.column_include_list;
}
if (input.incremental_column_name) {
- // reference_column is stored as a string (column name)
- table.reference_column = input.incremental_column_name;
+ // reference_column is stored as an object with name and type
+ table.reference_column = {
+ name: input.incremental_column_name,
+ type: input.incremental_column_type || 'unknown',
+ };
}
tables.push(table);
} else if (connector === 'singer' || connector === 's3') {
@@ -317,11 +320,11 @@ export class PlatformApiController {
}
// Build changes for DynamoDB table entry
- // reference_column is stored as a string (column name), not an object
+ // reference_column is stored as an object with name and type
const changes: {
type?: string;
columns?: string[];
- reference_column?: string | null;
+ reference_column?: ReferenceColumn | null;
} = {};
@@ -332,8 +335,15 @@ export class PlatformApiController {
changes.columns = body.column_include_list;
}
if ('incremental_column_name' in body) {
- // reference_column is just the column name as a string
- changes.reference_column = body.incremental_column_name || null;
+ // reference_column is stored as an object with name and type
+ if (body.incremental_column_name) {
+ changes.reference_column = {
+ name: body.incremental_column_name,
+ type: body.incremental_column_type || 'unknown',
+ };
+ } else {
+ changes.reference_column = null;
+ }
}
// Update DynamoDB if there are changes
@@ -466,11 +476,13 @@ export class PlatformApiController {
});
}
+ const pipelineType = this.mapConnectorToDynamoType(connectorType);
this.logger.info('Syncing pipeline to Elasticsearch', {
customerName: user.customer_name,
pipelineId: body.id,
plugin,
connector: connectorType,
+ type: pipelineType,
properties,
inputId,
});
@@ -490,7 +502,7 @@ export class PlatformApiController {
cron: body.cron,
tables: inputId,
properties,
- type: this.mapConnectorToDynamoType(connectorType),
+ type: pipelineType,
},
connector,
);
diff --git a/src/services/dynamodb/dynamodb.service.ts b/src/services/dynamodb/dynamodb.service.ts
index 099eb99..15dde41 100644
--- a/src/services/dynamodb/dynamodb.service.ts
+++ b/src/services/dynamodb/dynamodb.service.ts
@@ -11,6 +11,11 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
import { v4 as uuid } from 'uuid';
import { DYNAMODB_CONFIG } from './dynamodb.config';
+export interface ReferenceColumn {
+ name: string;
+ type: string;
+}
+
export interface InputDocument {
id: string;
client_id: string;
@@ -24,7 +29,7 @@ export interface InputDocument {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}>;
credentials?: Record;
}
@@ -62,7 +67,7 @@ export class DynamoDBService {
name: string;
type: string;
columns?: string[];
- reference_column?: string;
+ reference_column?: ReferenceColumn;
}>;
},
): Promise {
@@ -157,7 +162,7 @@ export class DynamoDBService {
changes: {
type?: string;
columns?: string[];
- reference_column?: string | null;
+ reference_column?: ReferenceColumn | null;
},
): Promise {
const dynamoTableName = DYNAMODB_CONFIG.inputsTable();
From bce73fb11f3b03f65f06df953f25ebfb627502ed Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Wed, 17 Dec 2025 17:24:03 -0300
Subject: [PATCH 37/41] FEAT: update user route
---
docsfera.json | 36 +++++++---------------------
package-lock.json | 9 +++----
package.json | 4 ++--
src/modules/roles/roles.service.ts | 38 +++++++++++++++++-------------
src/modules/users/dtos/entities.ts | 6 +++++
src/modules/users/users.service.ts | 15 +++++++-----
6 files changed, 53 insertions(+), 55 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index f1b040e..672c167 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -7225,33 +7225,6 @@
]
}
},
- "/platform/pipeline/pipeline_run": {
- "post": {
- "operationId": "PlatformApiController_createPipelineRun",
- "summary": "Create a pipeline run",
- "parameters": [],
- "responses": {
- "201": {
- "description": "",
- "content": {
- "application/json": {
- "schema": {
- "type": "object"
- }
- }
- }
- }
- },
- "tags": [
- "Platform API"
- ],
- "security": [
- {
- "access-token": []
- }
- ]
- }
- },
"/platform/pipeline/{pipelineId}/pipeline_run": {
"get": {
"operationId": "PlatformApiController_getPipelineRuns",
@@ -8523,6 +8496,15 @@
"hierarchy": {
"type": "string"
},
+ "bio": {
+ "type": "string"
+ },
+ "companySite": {
+ "type": "string"
+ },
+ "companyName": {
+ "type": "string"
+ },
"roleNames": {
"type": "array",
"items": {
diff --git a/package-lock.json b/package-lock.json
index 5248e39..002cc39 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.16",
+ "@dadosfera/protospack-v2": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
@@ -2970,9 +2970,10 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
- "version": "3.38.0-beta.16",
- "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.16.tgz",
- "integrity": "sha512-ijURcmETXdgVgXhIPxapK7w0z6begXm4WDZ6EJtUGg+oYlJd9QOxbwaD7akRzW8XTdccmIo0Vov065KB812J0A==",
+ "version": "0.0.0",
+ "resolved": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
+ "integrity": "sha512-ncpMpqOES0IqEnYMigS2lFIqCVSg3gsWENQzCeEaEkpnxidIHthBniJlUfr3ihPBSGg79OvGM5Cq7Yvyru66Ag==",
+ "license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.9.3",
"rxjs": "^7.5.5"
diff --git a/package.json b/package.json
index 4a5420d..6e51bcb 100644
--- a/package.json
+++ b/package.json
@@ -30,12 +30,12 @@
"@aws-crypto/sha256-js": "^5.2.0",
"@aws-sdk/client-dynamodb": "^3.414.0",
"@aws-sdk/client-secrets-manager": "^3.414.0",
- "@aws-sdk/lib-dynamodb": "^3.414.0",
"@aws-sdk/credential-provider-node": "^3.940.0",
+ "@aws-sdk/lib-dynamodb": "^3.414.0",
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.16",
+ "@dadosfera/protospack-v2": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
diff --git a/src/modules/roles/roles.service.ts b/src/modules/roles/roles.service.ts
index bd41ca5..d0045e5 100644
--- a/src/modules/roles/roles.service.ts
+++ b/src/modules/roles/roles.service.ts
@@ -229,27 +229,33 @@ export class RolesService {
const [roleTreated] = this.getRolesPermissionsName([role.role]);
return { role: roleTreated };
}
+
getRolesPermissionsName(roles: GetRolesPermissionsName[]): RoleDto[] {
const newRoles: RoleDto[] = [];
for (const role of roles) {
- const allPermissions = this.permissionsService.getAllPermissions(
- this.language,
- );
- const newPermissions = role.permissions.map((p) => {
- const permission = allPermissions.find((per) => per.seqid === p.seqid);
- return {
- ...p,
- name: permission.name,
- id: p.seqid,
- };
- });
- const newRole: RoleDto = {
- ...role,
- permissions: newPermissions,
- isPublic: role.isPublic,
- };
+ const newRole: RoleDto = this.formatRole(role);
newRoles.push(newRole);
}
return newRoles;
}
+
+ private formatRole(role: GetRolesPermissionsName): RoleDto {
+ const allPermissions = this.permissionsService.getAllPermissions(
+ this.language
+ );
+ const newPermissions = role.permissions.map((p) => {
+ const permission = allPermissions.find((per) => per.seqid === p.seqid);
+ return {
+ ...p,
+ name: permission.name,
+ id: p.seqid,
+ };
+ });
+
+ return {
+ ...role,
+ permissions: newPermissions,
+ isPublic: role.isPublic,
+ };;
+ }
}
diff --git a/src/modules/users/dtos/entities.ts b/src/modules/users/dtos/entities.ts
index 8e8b852..ac35213 100644
--- a/src/modules/users/dtos/entities.ts
+++ b/src/modules/users/dtos/entities.ts
@@ -109,6 +109,12 @@ export class UpdateUserReq {
@ApiPropertyOptional()
hierarchy?: string;
@ApiPropertyOptional()
+ bio?: string;
+ @ApiPropertyOptional()
+ companySite?: string;
+ @ApiPropertyOptional()
+ companyName?: string;
+ @ApiPropertyOptional()
roleNames?: string[];
}
diff --git a/src/modules/users/users.service.ts b/src/modules/users/users.service.ts
index 3057010..065a768 100644
--- a/src/modules/users/users.service.ts
+++ b/src/modules/users/users.service.ts
@@ -148,20 +148,23 @@ export class UsersService implements OnModuleInit {
}
async updateUser(req: UpdateUserReq, id: string, customerId: string) {
- const { department, hierarchy, jobTitle, name, roleNames, email } = req;
+ const { roleNames, ...updateUserDTO } = req;
if (roleNames) {
await this.setRoles({ roleNames, userId: id }, customerId);
}
const { user } = await lastValueFrom(
this.usersClientService.UserUpdate({
- name,
+ department: updateUserDTO.department,
+ email: updateUserDTO.email,
+ hierarchy: updateUserDTO.hierarchy,
+ jobTitle: updateUserDTO.jobTitle,
+ name: updateUserDTO.name,
+ bio: updateUserDTO.bio,
+ companyName: updateUserDTO.companyName,
+ companySite: updateUserDTO.companySite,
customerId,
id,
- department,
- hierarchy,
- jobTitle,
- email,
metabaseUserId: undefined,
}),
);
From 7f5d157739871680f2dec57a2c4fcd9eba3b34bf Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Thu, 18 Dec 2025 09:52:11 -0300
Subject: [PATCH 38/41] FEAT: update protospack version
---
package-lock.json | 76 ++++++++++++++++++++++++++---------------------
package.json | 2 +-
2 files changed, 43 insertions(+), 35 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 002cc39..7b0f852 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
+ "@dadosfera/protospack-v2": "3.38.0-beta.17",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
@@ -377,6 +377,7 @@
"resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.946.0.tgz",
"integrity": "sha512-sMmJRa2Y+jQ+qMzx7V3SBKsTSQzLBvSuVbMNM/YGSZkr849a4a6Frl4U8HfFj4O+o71dvQ6h5PP6vlc/fW672g==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
@@ -2412,6 +2413,7 @@
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.2",
@@ -2970,9 +2972,9 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
- "version": "0.0.0",
- "resolved": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
- "integrity": "sha512-ncpMpqOES0IqEnYMigS2lFIqCVSg3gsWENQzCeEaEkpnxidIHthBniJlUfr3ihPBSGg79OvGM5Cq7Yvyru66Ag==",
+ "version": "3.38.0-beta.17",
+ "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.17.tgz",
+ "integrity": "sha512-3E6m0ZKy5QOfuuTig05RC7Kj+zrh1GqZlTp6aePECDTrIyLhp2GIrALqJuD3LEjT+LG6eA88X2b4iXfV17Qmkg==",
"license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.9.3",
@@ -3822,6 +3824,7 @@
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.4.3.tgz",
"integrity": "sha512-Gd6D4IaYj01o14Bwv81ukidn4w3bPHCblMUq+SmUmWLyosK+XQmInCS09SbDDZyL8jy86PngtBLTdhJ2bXSUig==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"iterare": "1.2.1",
"tslib": "2.5.3",
@@ -3900,6 +3903,7 @@
"integrity": "sha512-Qi63+wi55Jh4sDyaj5Hhx2jOpKqT386aeo+VOKsxnd+Ql9VvkO/FjmuwBGUyzkJt29ENYc+P0Sx/k5LtstNpPQ==",
"hasInstallScript": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@nuxtjs/opencollective": "0.3.2",
"fast-safe-stringify": "2.1.1",
@@ -4037,6 +4041,7 @@
"resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-9.4.3.tgz",
"integrity": "sha512-FpdczWoRSC0zz2dNL9u2AQLXKXRVtq4HgHklAhbL59X0uy+mcxhlSThG7DHzDMkoSnuuHY8ojDVf7mDxk+GtCw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"body-parser": "1.20.2",
"cors": "2.8.5",
@@ -4400,6 +4405,7 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"license": "Apache-2.0",
+ "peer": true,
"engines": {
"node": ">=8.0.0"
}
@@ -4559,6 +4565,7 @@
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
"integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"cluster-key-slot": "1.1.2",
"generic-pool": "3.9.0",
@@ -5384,6 +5391,7 @@
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
@@ -5464,6 +5472,7 @@
"integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"jest-diff": "^27.0.0",
"pretty-format": "^27.0.0"
@@ -5527,7 +5536,8 @@
"version": "16.18.126",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
"integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@types/oauth": {
"version": "0.9.6",
@@ -5757,6 +5767,7 @@
"integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
"dev": true,
"license": "BSD-2-Clause",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.62.0",
"@typescript-eslint/types": "5.62.0",
@@ -6103,6 +6114,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -6199,6 +6211,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -6827,6 +6840,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
@@ -6933,6 +6947,7 @@
"resolved": "https://registry.npmjs.org/cache-manager/-/cache-manager-5.7.6.tgz",
"integrity": "sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"eventemitter3": "^5.0.1",
"lodash.clonedeep": "^4.5.0",
@@ -7156,13 +7171,15 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/class-validator": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
"integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/validator": "^13.11.8",
"libphonenumber-js": "^1.10.53",
@@ -7826,7 +7843,8 @@
"version": "0.0.1425554",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1425554.tgz",
"integrity": "sha512-uRfxR6Nlzdzt0ihVIkV+sLztKgs7rgquY/Mhcv1YNCWDh5IZgl5mnn2aeEnW5stYTE0wwiF4RYVz8eMEpV1SEw==",
- "license": "BSD-3-Clause"
+ "license": "BSD-3-Clause",
+ "peer": true
},
"node_modules/dezalgo": {
"version": "1.0.4",
@@ -8103,7 +8121,6 @@
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">= 0.8"
}
@@ -8291,6 +8308,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -8637,7 +8655,6 @@
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
@@ -8684,7 +8701,6 @@
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.5",
@@ -8709,7 +8725,6 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">= 0.6"
}
@@ -8719,7 +8734,6 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -8728,22 +8742,19 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/express/node_modules/path-to-regexp": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/express/node_modules/qs": {
"version": "6.13.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
- "peer": true,
"dependencies": {
"side-channel": "^1.0.6"
},
@@ -8772,8 +8783,7 @@
"url": "https://feross.org/support"
}
],
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/external-editor": {
"version": "3.1.0",
@@ -9008,7 +9018,6 @@
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"license": "MIT",
- "peer": true,
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~2.0.0",
@@ -9027,7 +9036,6 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -9036,8 +9044,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/find-up": {
"version": "5.0.0",
@@ -9831,6 +9838,7 @@
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.1.tgz",
"integrity": "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
@@ -10172,6 +10180,7 @@
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@jest/core": "^27.5.1",
"import-local": "^3.0.2",
@@ -11461,7 +11470,6 @@
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
- "peer": true,
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
@@ -12234,6 +12242,7 @@
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"passport-strategy": "1.x.x",
"pause": "0.0.1",
@@ -12623,6 +12632,7 @@
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"prettier": "bin-prettier.js"
},
@@ -13125,7 +13135,8 @@
"version": "0.1.14",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz",
"integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==",
- "license": "Apache-2.0"
+ "license": "Apache-2.0",
+ "peer": true
},
"node_modules/relative-microtime": {
"version": "2.0.0",
@@ -13312,6 +13323,7 @@
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"license": "Apache-2.0",
+ "peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
@@ -13373,6 +13385,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -13416,7 +13429,6 @@
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -13441,7 +13453,6 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"ms": "2.0.0"
}
@@ -13450,15 +13461,13 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">= 0.8"
}
@@ -13467,8 +13476,7 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
@@ -13484,7 +13492,6 @@
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
@@ -14462,6 +14469,7 @@
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -14691,6 +14699,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -15018,7 +15027,6 @@
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
diff --git a/package.json b/package.json
index 6e51bcb..6bd76c9 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "file:../protospack-v2/dadosfera-protospack-v2-0.0.0.tgz",
+ "@dadosfera/protospack-v2": "3.38.0-beta.17",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
From 61109f8ae9d58f31a90f4b91e4e6e13f8ddffd33 Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Thu, 18 Dec 2025 10:24:29 -0300
Subject: [PATCH 39/41] FIX: send new user info
---
docsfera.json | 36 ++++++++++++++++++++++++++++++
package-lock.json | 8 +++----
package.json | 2 +-
src/modules/users/dtos/entities.ts | 6 +++++
4 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index 672c167..d79ce2d 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -8166,6 +8166,15 @@
"hierarchy": {
"type": "string"
},
+ "bio": {
+ "type": "string"
+ },
+ "companyName": {
+ "type": "string"
+ },
+ "companySite": {
+ "type": "string"
+ },
"mfaStatus": {
"type": "string"
},
@@ -8196,6 +8205,9 @@
"jobTitle",
"department",
"hierarchy",
+ "bio",
+ "companyName",
+ "companySite",
"mfaStatus",
"createdAt",
"updatedAt",
@@ -8329,6 +8341,15 @@
"hierarchy": {
"type": "string"
},
+ "bio": {
+ "type": "string"
+ },
+ "companyName": {
+ "type": "string"
+ },
+ "companySite": {
+ "type": "string"
+ },
"customer": {
"$ref": "#/components/schemas/Customer"
},
@@ -8356,6 +8377,9 @@
"jobTitle",
"department",
"hierarchy",
+ "bio",
+ "companyName",
+ "companySite",
"mfaStatus",
"createdAt",
"updatedAt",
@@ -8545,6 +8569,15 @@
"hierarchy": {
"type": "string"
},
+ "bio": {
+ "type": "string"
+ },
+ "companyName": {
+ "type": "string"
+ },
+ "companySite": {
+ "type": "string"
+ },
"mfaStatus": {
"type": "string"
},
@@ -8568,6 +8601,9 @@
"jobTitle",
"department",
"hierarchy",
+ "bio",
+ "companyName",
+ "companySite",
"mfaStatus",
"createdAt",
"updatedAt",
diff --git a/package-lock.json b/package-lock.json
index 7b0f852..6f67e12 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.17",
+ "@dadosfera/protospack-v2": "3.38.0-beta.18",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
@@ -2972,9 +2972,9 @@
}
},
"node_modules/@dadosfera/protospack-v2": {
- "version": "3.38.0-beta.17",
- "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.17.tgz",
- "integrity": "sha512-3E6m0ZKy5QOfuuTig05RC7Kj+zrh1GqZlTp6aePECDTrIyLhp2GIrALqJuD3LEjT+LG6eA88X2b4iXfV17Qmkg==",
+ "version": "3.38.0-beta.18",
+ "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.18.tgz",
+ "integrity": "sha512-rD2UOKa0P17A6YXIpclXF7F9b86mhRNE7fImTrbFamOcHpGmXBBVU8U53mCfLzzOA+MdDZ4/1uDNurCyQCjsLQ==",
"license": "ISC",
"dependencies": {
"@grpc/grpc-js": "^1.9.3",
diff --git a/package.json b/package.json
index 6bd76c9..0aaef32 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"@aws-sdk/signature-v4": "^3.370.0",
"@dadosfera/dadosfera-logs": "^1.0.0-beta.4",
"@dadosfera/protospack": "2.5.3",
- "@dadosfera/protospack-v2": "3.38.0-beta.17",
+ "@dadosfera/protospack-v2": "3.38.0-beta.18",
"@grpc/grpc-js": "^1.9.3",
"@grpc/proto-loader": "^0.7.9",
"@nestjs/cli": "^9.5.0",
diff --git a/src/modules/users/dtos/entities.ts b/src/modules/users/dtos/entities.ts
index ac35213..0f0e5a3 100644
--- a/src/modules/users/dtos/entities.ts
+++ b/src/modules/users/dtos/entities.ts
@@ -38,6 +38,12 @@ export class User {
department?: string;
@ApiProperty()
hierarchy?: string;
+ @ApiProperty()
+ bio?: string;
+ @ApiProperty()
+ companyName?: string;
+ @ApiProperty()
+ companySite?: string;
@ApiPropertyOptional()
customer?: Customer;
@ApiProperty()
From f61c241dde9eb102ca46819a992afc59b9b86ffd Mon Sep 17 00:00:00 2001
From: Rafael
Date: Thu, 18 Dec 2025 10:30:09 -0300
Subject: [PATCH 40/41] FIX: inject customer_id in pipeline
execute/pause/unpause routes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Users no longer need to provide customer_id in the request body for
execute, pause, and unpause pipeline operations - it's now automatically
injected from the authenticated user's session.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5
---
.../platform-api/platform-api.controller.ts | 24 ++++++++++++++++---
1 file changed, 21 insertions(+), 3 deletions(-)
diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts
index 78b273e..e0d59f2 100644
--- a/src/modules/platform-api/platform-api.controller.ts
+++ b/src/modules/platform-api/platform-api.controller.ts
@@ -630,21 +630,39 @@ export class PlatformApiController {
@ApiOperation({ summary: 'Execute a pipeline' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
async executePipeline(@Body() body: any, @User() user: RequestUser) {
- return this.platformApiService.proxy('POST', '/pipeline/execute', user, body);
+ // Inject customer_id (actually customer_name) into body for Platform-API
+ // Note: Platform-API was created before customer_id existed, so it expects customer_name in the customer_id field
+ const enrichedBody = {
+ ...body,
+ customer_id: user.customer_name,
+ };
+ return this.platformApiService.proxy('POST', '/pipeline/execute', user, enrichedBody);
}
@Post('pipeline/pause')
@ApiOperation({ summary: 'Pause a pipeline' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
async pausePipeline(@Body() body: any, @User() user: RequestUser) {
- return this.platformApiService.proxy('POST', '/pipeline/pause', user, body);
+ // Inject customer_id (actually customer_name) into body for Platform-API
+ // Note: Platform-API was created before customer_id existed, so it expects customer_name in the customer_id field
+ const enrichedBody = {
+ ...body,
+ customer_id: user.customer_name,
+ };
+ return this.platformApiService.proxy('POST', '/pipeline/pause', user, enrichedBody);
}
@Post('pipeline/unpause')
@ApiOperation({ summary: 'Unpause a pipeline' })
@RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE)
async unpausePipeline(@Body() body: any, @User() user: RequestUser) {
- return this.platformApiService.proxy('POST', '/pipeline/unpause', user, body);
+ // Inject customer_id (actually customer_name) into body for Platform-API
+ // Note: Platform-API was created before customer_id existed, so it expects customer_name in the customer_id field
+ const enrichedBody = {
+ ...body,
+ customer_id: user.customer_name,
+ };
+ return this.platformApiService.proxy('POST', '/pipeline/unpause', user, enrichedBody);
}
@Put('pipeline/:pipelineId/memory')
From 8b93d4e97b5658be357116a3ebc0a84eaf3bc393 Mon Sep 17 00:00:00 2001
From: Marcos Rodrigues
Date: Thu, 18 Dec 2025 12:32:53 -0300
Subject: [PATCH 41/41] FEAT: protected update route with admin seqid or if
user request to equal a jwt user id claim
---
docsfera.json | 3 ---
src/modules/users/users.controller.ts | 5 ++++-
src/modules/users/users.service.ts | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/docsfera.json b/docsfera.json
index d79ce2d..68b2806 100644
--- a/docsfera.json
+++ b/docsfera.json
@@ -1321,9 +1321,6 @@
"Users"
],
"security": [
- {
- "access-token": []
- },
{
"access-token": []
}
diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts
index e565f18..b5cb32b 100644
--- a/src/modules/users/users.controller.ts
+++ b/src/modules/users/users.controller.ts
@@ -266,7 +266,6 @@ export class UsersController {
}
@Patch(':id')
- @RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
@ApiOkResponse({ type: UpdateUserRes })
async updateUser(
@User() user: RequestUser,
@@ -274,6 +273,10 @@ export class UsersController {
@Param('id') id: string,
@Language() language: LanguageEnum,
) {
+
+ if (user.user_id !== id || !user.permissions.includes(PERMISSIONS_GROUPS.USERS.permissions.ADMIN.seqid)) {
+ throw new ErrorBuilder(ErrorCodes.AUTH.FORBIDDEN);
+ }
this.logger.info('updateUser', { user });
this.userService.setLanguage(language);
return await this.userService.updateUser(body, id, user.customer_id);
diff --git a/src/modules/users/users.service.ts b/src/modules/users/users.service.ts
index 065a768..278188c 100644
--- a/src/modules/users/users.service.ts
+++ b/src/modules/users/users.service.ts
@@ -149,7 +149,7 @@ export class UsersService implements OnModuleInit {
async updateUser(req: UpdateUserReq, id: string, customerId: string) {
const { roleNames, ...updateUserDTO } = req;
- if (roleNames) {
+ if (roleNames && roleNames.length > 0) {
await this.setRoles({ roleNames, userId: id }, customerId);
}