NestJS: Resolving dependencies in NestMiddleware? - express-session

I'm trying to combine express-session with a typeorm storage within NestJS framework. Therefore I wrote a NestMiddleware as wrapper for express-session (see below). When I start node, NestJS logs the following
Error message:
UnhandledPromiseRejectionWarning: Unhandled promise rejection
(rejection id: 1): Error: Nest can't resolve dependencies of the
SessionMiddleware (?). Please verify whether [0] argument is available
in the current context.
Express is not started (connection refused), but the Sqlite DB (where the sessions should be stored) is created (also a session table, but not the columns).
To me it looks like there is a special problem in resolving dependencies with #InjectRepository from nestjs/typorm-Module. Does anyone have a hint?
Code:
import { Middleware, NestMiddleware, ExpressMiddleware } from '#nestjs/common';
import * as expressSession from 'express-session';
import { InjectRepository } from '#nestjs/typeorm';
import { Repository } from 'typeorm';
import { TypeormStore } from 'connect-typeorm';
import { Session } from './session.entity';
#Middleware()
export class SessionMiddleware implements NestMiddleware {
constructor(
#InjectRepository(Session)
private readonly sessionRepository: Repository<Session>
) {}
resolve(): ExpressMiddleware {
return expressSession({
store: new TypeormStore({ ttl: 86400 }).connect(this.sessionRepository),
secret: 'secret'
});
}
}

It was my fault. Had the middleware in a module, but was configuring the session middleware at the app module level. On that level the following import statement was missing:
TypeOrmModule.forFeature([Session])
Moved now everything to non-app module including middleware configuration. That solved the problem.

Related

No migrations are pending using Typeorm CLI and NestJS

The issue I'm facing is with running migrations using #nestjs/typeorm ^9.0.1 and typeorm ^0.3.12. Despite being able to build the project and create migrations, when I try to run them, typeorm can't find the migration files (No migrations are pending).
I have noticed that the version 0.3.x of typeorm requires Datasource object and that in the version 9.x of #nestjs/typeorm, TypeOrmModuleOptions does not have the cli : {migrationsDir : string} attribute.
Here's a link to the project that reproduces the problem, and an example directory structure :
src\configs\database\dataSource.config.ts
src\configs\database\postgres.config.ts
src\configs\database\migrations\1676252827402-Chat.ts
postgres.config.ts
import { DataSourceOptions } from "typeorm";
import { join } from "path";
import { config } from "dotenv";
import CustomNamingStrategy from "./customNamingStrategy";
import { registerAs } from "#nestjs/config";
import { TypeOrmModuleOptions } from "#nestjs/typeorm";
config();
export const databaseConfig: DataSourceOptions = {
name: "default",
type: "postgres",
url: process.env.DATABASE_URL,
ssl:
process.env.DATABASE_ENABLE_SSL === "true"
? {
rejectUnauthorized: false,
}
: false,
logging: process.env.DATABASE_ENABLE_LOGGING === "true",
entities: [join(__dirname, "../../models/*/", "*.entity.{ts,js}")],
migrations: [join(__dirname, "migrations/*.{ts,js}")],
synchronize: false,
migrationsRun: false,
namingStrategy: new CustomNamingStrategy(),
};
export default registerAs(
"database",
() =>
({
...databaseConfig,
keepConnectionAlive: true,
} as TypeOrmModuleOptions)
);
dataSource.config.ts
import { DataSource } from "typeorm";
import { databaseConfig } from "./postgres.config";
export const AppDataSource = new DataSource(databaseConfig);
package.json
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli"
"migration:create": "yarn run typeorm migration:create"
"migration:run": "yarn run typeorm migration:run -d src/configs/database/dataSource.config.ts"
Although I can use the create command successfully, when I use the run command, it only displays the message "No migrations are pending". I attempted to resolve the issue by changing migrations path to the DataSourceOptions.migrations list, but it did not work. I also tried replacing the cli parameter datasource with the dist datasource, as well as adjusting the migration paths, but these changes did not fix the issue.
I'm facing a similar issue using the same version of typeorm (^0.3.12), so there might be a bug in this version.
It seems that the migrations are not found anymore if the DataSourceOptions.migrations property is set with the path to the migrations folder.
The ^0.3.12 version seems to be working fine only if the migration classes are directly referenced in DataSourceOptions.migrations, similar to the following:
import { Chat1676252827402 } from './migrations/1676252827402-Chat.ts';
export const databaseConfig: DataSourceOptions = {
...
migrations: [Chat1676252827402],
...
};

Use process.env inside imported const in jest

I have a config file that exports some info for my app.
export const config: Config = {
isProd: process.env.NODE_ENV == 'production',
connection: {
port: parseInt(process.env.APP_PORT) || 2000,
},
};
And I want to import it and use inside my e2e jest test.
import {Test, TestingModule} from "#nestjs/testing";
import {INestApplication} from "#nestjs/common";
import * as request from "supertest";
import {AppModule} from "./../src/app.module";
import * as dotenv from "dotenv";
dotenv.config({path: ".env"});
import {config} from "../src/infrastructure/config/config"
console.log(process.env); // available here
console.log(config); // will return default values, not from .env
// ...
How can i make jest use env inside imported module?
Nestjs has great configuration modules that support .env:
https://docs.nestjs.com/techniques/configuration#custom-env-file-path
Makes it really easy to ref your configuration in all of your services as opposed to having to import.

Google Cloud Function works in emulator but errs on deploy to Firebase: Unexpected token p in JSON at position 1

I have a cloud function that is meant to delete a post with its subcollection of comments. It properly deletes the post in the emulator. However, when I try to deploy the cloud function to Firebase the following error occurs:
i functions: updating Node.js 16 function
recursiveDelete(us-central1)...
Function failed on loading user code. This is likely due to a bug in
the user code. Error message:
Error: please examine your function logs to see the error cause:
https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs.
Additional troubleshooting documentation can be found at
https://cloud.google.com/functions/docs/troubleshooting#logging.
Functions deploy had errors with the following functions:
recursiveDelete(us-central1)
As instructed, I checked the error in the log in Google Cloud I found:
SyntaxError: Unexpected token p in JSON at position 1
at .JSON.parse
at .parse (
/layers/google.nodejs.functions-framework/functions-framework/node_modules/body-parser/lib/types/json.js:89
)
This is the function:
const functions = require("firebase-functions");
const firebase_tools = require('firebase-tools');
const admin = require('firebase-admin');
admin.initializeApp();
/**
* Initiate a recursive delete of documents at a given path.
* #param {string} data.path the document or collection path to delete.
*/
exports.recursiveDelete = functions
.runWith({
timeoutSeconds: 540,
memory: '2GB'
})
.https.onCall(async (data, context) => {
const path = data[0].path;
console.log(`Running cloud function recursiveDelete on ${path}`);
await firebase_tools.firestore
.delete(path, {
project: process.env.GCP_PROJECT,
recursive: true,
yes: true,
token: '...',
force: true
});
return {
path: path
};
});
This is how I'm calling it:
static Future<void> delete(String ref) async {
if (FirebaseAuth.instance.currentUser == null) {
throw Exception('Must be logged in');
}
await FirebaseFunctions.instance
.httpsCallable('recursiveDelete')
.call([{'path': 'posts/$ref'}])
.then((value) => logger("Post deleted: ${value.data}"))
.catchError((error) => logger.error("Failed to delete post: $error"));
}
In the emulator, deletion works fine and the output is:
I/flutter (26907): [Post] [INFO] Post deleted: {path:
posts/Gk4TeWEgZmm0QUcaqTrk}
So, what's wrong with it?
Full stack-trace:
=== Deploying to 'sightings-dev'...
i deploying functions
i functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔ functions: required API cloudfunctions.googleapis.com is enabled
✔ functions: required API cloudbuild.googleapis.com is enabled
✔ artifactregistry: required API artifactregistry.googleapis.com is enabled
i functions: preparing codebase default for deployment
i functions: preparing functions directory for uploading...
i functions: packaged /Users/strijdhaftig/sightings/frontend/flutter/sightings/functions (55.13 KB) for uploading
✔ functions: functions folder uploaded successfully
i functions: updating Node.js 16 function recursiveDelete(us-central1)...
Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation.
Functions deploy had errors with the following functions:
recursiveDelete(us-central1)
i functions: cleaning up build files...
Error: There was an error deploying functions
Having trouble? Try again or contact support with contents of firebase-debug.log

Wasm-rust and postgres

is there a way to get data from a database in postgres using wasm?. I'd tried to get it using a library in rust but I got some errore when I build the package using "wasm-pack building--target web". The idea is to build a function in lib.rs file that return data from a db. I have the below code inside lib.rs:
use postgres::{Client, Error, NoTls};
use wasm_bindgen::prelude::*;
...
struct Author {
_id: i32,
name: String,
}
#[wasm_bindgen]
pub fn select_name(name: &String) -> Result<(), Error> {
let mut client = Client::connect("postgresql://user:1234#localhost:5432/db", NoTls)?;
for row in client.query(
"SELECT id, name FROM author WHERE name = $1",
&[&name],
)? {
let author = Author {
_id: row.get(0),
name: row.get(1),
};
println!(
"Select_Name => Author {} :",
author.name
);
}
Ok(())
}
but I get some errors:
error[E0432]: unresolved import `crate::sys::IoSourceState`
error[E0432]: unresolved import `crate::sys`
...
It is not possible directly (as Njuguna Mureithi rightly wrote) but it can be circumvented.
We can use the project: https://github.com/PostgREST/postgrest
and expose the API to our sql server.
We download the latest version of postgrest
https://github.com/PostgREST/postgrest/releases/tag/v9.0.0
in case of Linux we unpack
tar -xf postgrest-v9.0.0-linux-static-x64.tar.xz
then run help
./postgrest -h
create a configuration file for ./postgrest
postgrest -e > cfg.psqlrest
change the user and password for the database in the configuration file.
e.g. with
db-uri = "postgres://user:pasword#localhost:5432/dbname"
to your dbname database access user:pasword configuration
db-uri = "postgres://postgres:zaqwsxc#localhost:5432/dbname"
and run the server which will issue the api to our postgres
./postgrest cfg.psqlrest
The address http://localhost:3000 will start accessing the database dbname, which must be created in the database server beforehand.
Here is a description of the libraries needed to call the query using the API.
https://rustwasm.github.io/wasm-bindgen/examples/fetch.html
examples of API
https://postgrest.org/en/stable/api.html

Unable to connect to MongoDB when using a URI with credentials

I'm trying to build a simple CRUD API with the MongoDB Rust driver but I'm failing to insert anything into the DB. I'm using Mlab to host my database.
The code that I'm running:
#[macro_use(bson, doc)]
extern crate bson;
extern crate mongodb;
use mongodb::db::ThreadedDatabase;
use mongodb::{Client, ThreadedClient};
fn main() {
let client = Client::with_uri(
"mongodb://<my_db_username>:<my_db_password>#ds235711.mlab.com:35711/rustcrud",
)
.expect("Failed to initialize client");
let coll = client.db("rustcrud").collection("test");
coll.insert_one(doc! { "title": "Back to the Future" }, None)
.unwrap();
}
And the error that I get:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: OperationError("not authorized on rustcrud to execute command { insert: \"test\", $db: \"rustcrud\" }")', libcore/result.rs:1009:5
What am I doing wrong?
From the project's GitHub repository, issue 256: Add auth to base examples
user-password authentication occurs at the database-level. The user, password, and database are parsed from the URI, but I don't believe we have it set up to automatically authenticate when you create the database object
let client = Client::with_uri("mongodb://x:y#localhost:27017")?;
client.auth("x", "y");