Skip to content

Commit

Permalink
Merge pull request #352 from lenneTech/develop
Browse files Browse the repository at this point in the history
Release 10.2.8
  • Loading branch information
kaihaase authored Jan 16, 2024
2 parents 98d2034 + 98a31d8 commit cceeb86
Show file tree
Hide file tree
Showing 9 changed files with 1,511 additions and 703 deletions.
1,961 changes: 1,335 additions & 626 deletions package-lock.json

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lenne.tech/nest-server",
"version": "10.2.7",
"version": "10.2.8",
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
"keywords": [
"node",
Expand Down Expand Up @@ -62,25 +62,25 @@
"node": ">= 16.13.0"
},
"dependencies": {
"@apollo/gateway": "2.5.7",
"@apollo/gateway": "2.6.3",
"@getbrevo/brevo": "1.0.1",
"@lenne.tech/mongoose-gridfs": "1.4.2",
"@lenne.tech/multer-gridfs-storage": "5.0.6",
"@nestjs/apollo": "12.0.11",
"@nestjs/common": "10.2.9",
"@nestjs/core": "10.2.9",
"@nestjs/common": "10.3.0",
"@nestjs/core": "10.3.0",
"@nestjs/graphql": "12.0.11",
"@nestjs/jwt": "10.2.0",
"@nestjs/mongoose": "10.0.2",
"@nestjs/passport": "10.0.2",
"@nestjs/platform-express": "10.2.9",
"@nestjs/passport": "10.0.3",
"@nestjs/platform-express": "10.3.0",
"@nestjs/schedule": "4.0.0",
"@nestjs/terminus": "10.1.1",
"@nestjs/terminus": "10.2.0",
"apollo-server-core": "3.13.0",
"apollo-server-express": "3.13.0",
"bcrypt": "5.1.1",
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
"class-validator": "0.14.1",
"compression": "1.7.4",
"cookie-parser": "1.4.6",
"ejs": "3.1.9",
Expand All @@ -93,45 +93,45 @@
"light-my-request": "5.11.0",
"lodash": "4.17.21",
"mongodb": "6.3.0",
"mongoose": "7.6.5",
"mongoose": "7.6.8",
"multer": "1.4.5-lts.1",
"node-mailjet": "6.0.4",
"nodemailer": "6.9.7",
"nodemon": "3.0.1",
"passport": "0.6.0",
"node-mailjet": "6.0.5",
"nodemailer": "6.9.8",
"nodemon": "3.0.2",
"passport": "0.7.0",
"passport-jwt": "4.0.1",
"reflect-metadata": "0.1.13",
"reflect-metadata": "0.1.14",
"rfdc": "1.3.0",
"rimraf": "5.0.5",
"rxjs": "7.8.1",
"yuml-diagram": "1.2.0"
},
"devDependencies": {
"@babel/plugin-proposal-private-methods": "7.18.6",
"@compodoc/compodoc": "1.1.22",
"@lenne.tech/eslint-config-ts": "0.0.10",
"@nestjs/cli": "10.2.1",
"@nestjs/schematics": "10.0.3",
"@nestjs/testing": "10.2.9",
"@compodoc/compodoc": "1.1.23",
"@lenne.tech/eslint-config-ts": "0.0.16",
"@nestjs/cli": "10.3.0",
"@nestjs/schematics": "10.1.0",
"@nestjs/testing": "10.3.0",
"@swc/cli": "0.1.63",
"@swc/core": "1.3.96",
"@swc/core": "1.3.103",
"@swc/jest": "0.2.29",
"@types/compression": "1.7.5",
"@types/cookie-parser": "1.4.6",
"@types/ejs": "3.1.5",
"@types/express": "4.17.21",
"@types/jest": "29.5.8",
"@types/lodash": "4.14.201",
"@types/multer": "1.4.10",
"@types/node": "20.9.1",
"@types/jest": "29.5.11",
"@types/lodash": "4.14.202",
"@types/multer": "1.4.11",
"@types/node": "20.11.3",
"@types/nodemailer": "6.4.14",
"@types/passport": "1.0.15",
"@types/supertest": "2.0.16",
"@typescript-eslint/eslint-plugin": "6.11.0",
"@typescript-eslint/parser": "6.11.0",
"@types/passport": "1.0.16",
"@types/supertest": "6.0.2",
"@typescript-eslint/eslint-plugin": "6.19.0",
"@typescript-eslint/parser": "6.19.0",
"coffeescript": "2.7.0",
"eslint": "8.54.0",
"eslint-config-prettier": "9.0.0",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-unused-imports": "3.0.0",
"find-file-up": "2.0.1",
"grunt": "1.6.1",
Expand All @@ -143,15 +143,15 @@
"jest": "29.7.0",
"npm-watch": "0.11.0",
"pm2": "5.3.0",
"prettier": "3.1.0",
"prettier": "3.2.2",
"pretty-quick": "3.1.3",
"supertest": "6.3.3",
"supertest": "6.3.4",
"ts-jest": "29.1.1",
"ts-loader": "9.5.1",
"ts-morph": "20.0.0",
"ts-node": "10.9.1",
"ts-node": "10.9.2",
"tsconfig-paths": "4.2.0",
"typescript": "5.2.2",
"typescript": "5.3.3",
"yalc": "1.0.0-pre.53"
},
"overrides": {
Expand Down
2 changes: 1 addition & 1 deletion spectaql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ servers:
info:
title: lT Nest Server
description: Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).
version: 10.2.7
version: 10.2.8
contact:
name: lenne.Tech GmbH
url: https://lenne.tech
Expand Down
22 changes: 12 additions & 10 deletions src/core/common/helpers/table.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,32 @@ export function htmlTable(
rows: string[][],
options?: {
tableStyle?: string;
tbodyStyle?: string;
tdStyle?: string;
thStyle?: string;
theadStyle?: string;
trHeadStyle?: string;
thStyle?: string;
tbodyStyle?: string;
trStyle?: string;
tdStyle?: string;
},
): string {
const config = {
tableStyle: 'width: 100%; border: 1px solid #000; border-collapse: collapse;',
trHeadStyle: 'background-color: #f0f0f0;',
tdStyle: 'border: 1px solid #000; padding: 10px;',
thStyle: 'border: 1px solid #000; padding: 10px;',
tcStyle: 'border: 1px solid #000; padding: 10px;',
trHeadStyle: 'background-color: #f0f0f0;',
...options,
};
let table = `<table style="${config.tableStyle}"><thead style="${config.theadStyle}"><tr style="${config.trHeadStyle}">`;
let table = `<table${config.tableStyle ? ` style="${config.tableStyle}"` : ''}><thead${
config.theadStyle ? ` style="${config.theadStyle}"` : ''
}><tr${config.trHeadStyle ? ` style="${config.trHeadStyle}"` : ''}>`;
for (const head of header) {
table += `<th style="${config.thStyle}">${head}</th>`;
table += `<th${config.thStyle ? ` style="${config.thStyle}"` : ''}>${head}</th>`;
}
table += '</tr></thead><tbody style="${config.tbodyStyle}">';
table += `</tr></thead><tbody${config.tbodyStyle ? ` style="${config.tbodyStyle}"` : ''}>`;
for (const row of rows) {
table += `<tr style="${config.trStyle}">`;
table += `<tr${config.trStyle ? ` style="${config.trStyle}"` : ''}>`;
for (const cell of row) {
table += `<td style="${config.tdStyle}">${cell}</td>`;
table += `<td${config.tdStyle ? ` style="${config.tdStyle}"` : ''}>${cell}</td>`;
}
table += '</tr>';
}
Expand Down
10 changes: 9 additions & 1 deletion src/core/common/interfaces/server-options.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,21 @@ export interface IServerOptions {
/**
* API key for Brevo
*/
apiKey?: string;
apiKey: string;

/**
* Regular expression for excluding (test) users
* e.g. /@testuser.com$/i
*/
exclude?: RegExp;

/**
* Default sender for Brevo
*/
sender: {
email: string;
name: string;
};
};

/**
Expand Down
20 changes: 17 additions & 3 deletions src/core/common/interfaces/service-options.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import { PrepareOutputOptions } from './prepare-output-options.interface';

/**
* General service options
*
* HINT:
* If this interface is extended (ServiceOptions & { ... }), then only properties that are not present in
* ServiceOptions may be added in order to avoid unwanted side effects. To ensure this (also for future changes to
* ServiceOptions), the properties of the extension should be provided with a prefix, e.g. with an underscore
* (ServiceOptions & {_myProperty: any}).
*/
export interface ServiceOptions {
// All fields are allowed to be compatible as far as possible
Expand Down Expand Up @@ -72,11 +78,19 @@ export interface ServiceOptions {
// Whether to publish action via GraphQL subscription
pubSub?: boolean;

// Whether to return raw data without preparation via prepareInput or prepareOutput (prepareInput and prepareOutput will be ignored)
// Compare raw functions in CrudService
raw?: boolean;

// Roles (as string) to check
roles?: string | string[];

// Select fields via mongoose select
// See https://mongoosejs.com/docs/api.html#query_Query-select
select?: string | string[] | Record<string, number | boolean | object>;

// Add updateBy and/or createBy user ID into input after check
// If falsy: input data will not be changed
// If truly (default): updatedBy and/or createdBy (when create mode is activated) will be set if current user is available
setCreateOrUpdateUserId?: boolean;

// Roles (as string) to check
roles?: string | string[];
}
51 changes: 47 additions & 4 deletions src/core/common/services/brevo.service.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@

import { Injectable } from '@nestjs/common';
import brevo = require('@getbrevo/brevo');
import { ConfigService } from './config.service';


@Injectable()
export class BrevoService {
brevoConfig: ConfigService['configFastButReadOnly']['brevo'];

constructor(protected configService: ConfigService) {
const defaultClient = brevo.ApiClient.instance;
const apiKey = defaultClient.authentications['api-key'];
apiKey.apiKey = configService.configFastButReadOnly.brevo?.apiKey;
if (!apiKey.apiKey) {
console.warn('Brevo API key not set!');
this.brevoConfig = configService.configFastButReadOnly.brevo;
if (!this.brevoConfig) {
throw new Error('Brevo configuration not set!');
}
apiKey.apiKey = this.brevoConfig.apiKey;
}

/**
* Send a transactional email via Brevo
*/
async sendMail(to: string, templateId: number, params?: object): Promise<unknown> {

// Check input
if (!to || !templateId) {
return false;
Expand Down Expand Up @@ -45,4 +49,43 @@ export class BrevoService {
// Return null if error
return null;
}

/**
* Send HTML mail
*/
async sendHtmlMail(
to: string,
subject: string,
html: string,
options?: { params?: Record<string, string> },
): Promise<unknown> {
// Check input
if (!to || !subject || !html) {
return false;
}

// Exclude (test) users
if (this.brevoConfig.exclude?.test?.(to)) {
return 'TEST_USER!';
}

// Prepare data
const apiInstance = new brevo.TransactionalEmailsApi();
const sendSmtpEmail = new brevo.SendSmtpEmail();
sendSmtpEmail.htmlContent = html;
sendSmtpEmail.params = options?.params;
sendSmtpEmail.sender = this.brevoConfig.sender;
sendSmtpEmail.subject = subject;
sendSmtpEmail.to = [{ email: to }];

// Send email
try {
return await apiInstance.sendTransacEmail(sendSmtpEmail);
} catch (error) {
console.error(error);
}

// Return null if error
return null;
}
}
Loading

0 comments on commit cceeb86

Please sign in to comment.