Getting error while using env variables as ConfigService in NestJs - environment-variables

i'm using nestjs for project i have no issue using "#nestjs/config" before version 1.1.2 but when i created new one while copy paste from my old source code into my new one especially in main.ts it gives me error Argument of type 'string' is not assignable to parameter of type 'never'. when i passed string LISTENING_PORT into get function of configService but it worked in my old project what's the problem and how to solve this problem? thanks in advance.
here's my sample code
import { ConfigService } from '#nestjs/config';
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
import * as helmet from 'helmet';
import { CustomExceptionFilter } from './exceptions/custom-exception.filter';
import { CustomValidationPipe } from './pipes/custom-validation.pipe';
import { SwaggerModule, DocumentBuilder } from '#nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
app.use(helmet());
app.useGlobalPipes(new CustomValidationPipe());
const configService = app.get(ConfigService);
app.useGlobalFilters(new CustomExceptionFilter(configService));
const listeningPort = configService.get('LISTENING_PORT');
const config = new DocumentBuilder()
.setTitle('API Documentation')
.setDescription('API description')
.setVersion('0.1')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
await app.listen(listeningPort);
}
bootstrap();

Fixed on #nestjs/config version 1.1.3

Related

SQFLITE ERROR: SqfliteDatabaseException (DatabaseException(database_closed))

The two pages in the application are listed with database(sqlite). but when I want to switch between pages, I get such an error: SqfliteDatabaseException (DatabaseException(database_closed))
please help mee.. I don't understand why see this error.
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:bankingapp/models/coin.dart';
import 'package:bankingapp/models/histories.dart';
import 'package:flutter/services.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DbHelper {
static Database? _db;
Future<Database> get db async {
return _db ??= await initDb();
}
Future<Database> initDb() async {
var dbFolder = await getDatabasesPath();
String path = join(dbFolder, 'app.db');
// Delete any existing database:
await deleteDatabase(path);
// Create the writable database file from the bundled demo database file:
try {
await Directory(dirname(path)).create(recursive: true);
} catch (_) {}
ByteData data =
await rootBundle.load(join("assets/database", "bankingapp.db"));
List<int> bytes =
data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await new File(path).writeAsBytes(bytes, flush: true);
//open the database
return await openDatabase(path);
}
Future<List<Histories>> getHistories() async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT * FROM Histories");
return result.map((data) => Histories.fromMap(data)).toList();
}
Future<List<Coins>> getCoins() async {
var dbClient = await db;
var result = await dbClient.rawQuery("SELECT * FROM Coins");
return result.map((data) => Coins.fromMap(data)).toList();
}
}
I don't exactly know the answer but I suggest you to use Floor package. This is really simple to implement and it is the abstraction of SQLite database so I think it will be familiar to you. I don't seem to face such error with this package.
https://pub.dev/packages/floor

Vaadin 18 | Calling server from client using Littemplate

I am trying to call server side function from client using littemplate. I have checked examples on Vaadin site and found that client may call server side via this.$server._some_method.
I tried to use $server in littemplate but during frontend compilation vaadin throws error stating that "Property '$server' does not exist on type 'HelloWorld'."
Please let me know what is wrong with this program and guide me.
Thank you.
Littemplate
import {LitElement, html} from 'lit-element';
import '#vaadin/vaadin-button/vaadin-button.js';
class HelloWorld extends LitElement {
render() {
return html`
<div>
<vaadin-button id="helloButton">Click me!</vaadin-button>
</div>`;
}
sayHello(){
showNotification("Hello");
this.$server.greet(); //Problematic statement.
}
}
customElements.define('hello-world', HelloWorld);
Java
package com.example.application.littemplate;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.littemplate.LitTemplate;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.template.Id;
import com.vaadin.flow.component.textfield.TextField;
//HelloWorld.java
#Tag("hello-world")
#JsModule("./views/littemplate/hello-world.ts")
public class HelloWorld extends LitTemplate {
#Id
// Uses the vaadin-button id "helloButton"
private Button helloButton;
public HelloWorld() {
helloButton.addClickListener(event -> Notification.show("Hello " + nameField.getValue()));
}
#ClientCallable
public void greet() {
System.out.println("Hello server");
}
}
Typescript does not know that LitTemplate has a $server variable. You have to define it yourself.
You can use type any or define your interface.
For example:
private $server?: MyTestComponentServerInterface;
And add the #ClientCallable functions:
interface MyTestComponentServerInterface {
greet(): void;
}
In your case, your typescript could be:
import {LitElement, html} from 'lit-element';
import '#vaadin/vaadin-button/vaadin-button.js';
class HelloWorld extends LitElement {
private $server?: HelloWorldServerInterface;
render() {
return html`
<div>
<vaadin-button id="helloButton">Click me!</vaadin-button>
</div>`;
}
sayHello(){
showNotification("Hello");
this.$server!.greet(); // should work with autocompletion
}
}
interface HelloWorldServerInterface {
greet(): void;
}
customElements.define('hello-world', HelloWorld);

Passing feathers app object to TypeGraphQL using dependency injection

I can't figure out how to pass my app object to my TypeGrapQL resolvers.
I created my types and resolvers and setup a graphql server using express-graphql. I was able to run the graph, but no luck in passing the app object to use the registered services.
My graphql.service.ts looks like this:
import { ServiceAddons } from '#feathersjs/feathers'
import { graphqlHTTP } from 'express-graphql'
import 'reflect-metadata'
import { buildSchemaSync } from 'type-graphql'
import { Container } from 'typedi'
import { Application } from '../../declarations'
import { Graphql } from './graphql.class'
import { ArticleResolver } from './resolvers/article.resolver'
// Add this service to the service type index
declare module '../../declarations' {
interface ServiceTypes {
graphql: Graphql & ServiceAddons<any>
}
}
export default async function (app: Application): Promise<void> {
const schema = buildSchemaSync({
resolvers: [__dirname + '/resolvers/*.resolver.ts'],
container: Container,
})
app.use(
'/graphql',
graphqlHTTP({
schema: schema,
graphiql: true,
})
)
}
and here's one of my resolver classes article.resolver.ts
import { Arg, Query, Resolver } from 'type-graphql'
import { Service } from 'typedi'
import { Application } from '../../../declarations'
import { Category } from '../types/category.type'
#Service()
#Resolver(Category)
export class CategoryResolver {
constructor(private readonly app: Application) {}
#Query((returns) => [Category])
async categories() {
try {
const result = await this.app.service('category').find()
return (result as any).data // TODO: Refactor to return result with pagination details
} catch (err) {
console.log('Categories resolver error', err)
return []
}
}
}
I can't do this.app.service() as this.app is undefined
Im a little confused on how dependency injection works in TypeGrapQL, any help is appreciated.
Thanks
I managed to make it work, here's my solution if anyone has the same problem:
I created a Graphql class decorated with #Service from typedi that takes in an app object as such
import { Service } from 'typedi'
import { Application } from '../../declarations'
#Service()
export class Graphql {
app: Application
//eslint-disable-next-line #typescript-eslint/no-unused-vars
constructor(app: Application) {
this.app = app
}
}
In my graphql.service.ts I initiated the class and passed down the instance to the typedi container
import { buildSchemaSync } from 'type-graphql'
import { Container } from 'typedi'
import { Application } from '../../declarations'
import { Graphql } from './graphql.class'
export default async function (app: Application): Promise<void> {
const graphql = new Graphql(app)
Container.set('graphql', graphql)
const schema = buildSchemaSync({
resolvers: [__dirname + '/resolvers/category.resolver.ts'],
container: Container, // Pass the container to the resolvers
})
// Initialize our express graphql server
}
And Finally in my resolvers I am decorating the resolver with #Service and injecting the graphql instance to the constructor:
import { Application } from '../../../declarations'
import { Graphql } from '../graphql.class'
import { Inject, Service } from 'typedi'
#Service()
#Resolver(Category)
export class CategoryResolver {
app: Application
constructor(#Inject('graphql') private readonly graphql: Graphql) {
this.app = this.graphql.app
}
// Queries and Mutations
}
This solved it to me, hope it comes with any help to you 😊

Generate one file for a list of parsed files using source_gen in dart

I have a list of models that I need to create a mini reflective system.
I analyzed the Serializable package and understood how to create one generated file per file, however, I couldn't find how can I create one file for a bulk of files.
So, how to dynamically generate one file, using source_gen, for a list of files?
Example:
Files
user.dart
category.dart
Generated:
info.dart (containg information from user.dart and category.dart)
Found out how to do it with the help of people in Gitter.
You must have one file, even if empty, to call the generator. In my example, it is lib/batch.dart.
source_gen: ^0.5.8
Here is the working code:
The tool/build.dart
import 'package:build_runner/build_runner.dart';
import 'package:raoni_global/phase.dart';
main() async {
PhaseGroup pg = new PhaseGroup()
..addPhase(batchModelablePhase(const ['lib/batch.dart']));
await build(pg,
deleteFilesByDefault: true);
}
The phase:
batchModelablePhase([Iterable<String> globs =
const ['bin/**.dart', 'web/**.dart', 'lib/**.dart']]) {
return new Phase()
..addAction(
new GeneratorBuilder(const
[const BatchGenerator()], isStandalone: true
),
new InputSet(new PackageGraph.forThisPackage().root.name, globs));
}
The generator:
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'package:glob/glob.dart';
import 'package:build_runner/build_runner.dart';
class BatchGenerator extends Generator {
final String path;
const BatchGenerator({this.path: 'lib/models/*.dart'});
#override
Future<String> generate(Element element, BuildStep buildStep) async {
// this makes sure we parse one time only
if (element is! LibraryElement)
return null;
String libraryName = 'raoni_global', filePath = 'lib/src/model.dart';
String className = 'Modelable';
// find the files at the path designed
var l = buildStep.findAssets(new Glob(path));
// get the type of annotation that we will use to search classes
var resolver = await buildStep.resolver;
var assetWithAnnotationClass = new AssetId(libraryName, filePath);
var annotationLibrary = resolver.getLibrary(assetWithAnnotationClass);
var exposed = annotationLibrary.getType(className).type;
// the caller library' name
String libName = new PackageGraph.forThisPackage().root.name;
await Future.forEach(l.toList(), (AssetId aid) async {
LibraryElement lib;
try {
lib = resolver.getLibrary(aid);
} catch (e) {}
if (lib != null && Utils.isNotEmpty(lib.name)) {
// all objects within the file
lib.units.forEach((CompilationUnitElement unit) {
// only the types, not methods
unit.types.forEach((ClassElement el) {
// only the ones annotated
if (el.metadata.any((ElementAnnotation ea) =>
ea.computeConstantValue().type == exposed)) {
// use it
}
});
});
}
});
return '''
$libName
''';
}
}
It seems what you want is what this issue is about How to generate one output from many inputs (aggregate builder)?
[Günter]'s answer helped me somewhat.
Buried in that thread is another thread which links to a good example of an aggregating builder:
1https://github.com/matanlurey/build/blob/147083da9b6a6c70c46eb910a3e046239a2a0a6e/docs/writing_an_aggregate_builder.md
The gist is this:
import 'package:build/build.dart';
import 'package:glob/glob.dart';
class AggregatingBuilder implements Builder {
/// Glob of all input files
static final inputFiles = new Glob('lib/**');
#override
Map<String, List<String>> get buildExtensions {
/// '$lib$' is a synthetic input that is used to
/// force the builder to build only once.
return const {'\$lib$': const ['all_files.txt']};
}
#override
Future<void> build(BuildStep buildStep) async {
/// Do some operation on the files
final files = <String>[];
await for (final input in buildStep.findAssets(inputFiles)) {
files.add(input.path);
}
String fileContent = files.join('\n');
/// Write to the file
final outputFile = AssetId(buildStep.inputId.package,'lib/all_files.txt');
return buildStep.writeAsString(outputFile, fileContent);
}
}

parsing with dom4j

I am successfully retrieve the data of response using xpath expression /abcde/response from the xml ,
<abcde>
<response>000</response>
</abcde>
But couldnt retrieve the data of response from the same xml but with some additional data
<abcde version="8.1" xmlns="http://www.litle.com/schema"
response="0" message="Valid Format">
<response>000</response>
</abcde>
What am i doing wrong ?
package stackoverflow;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.DocumentHelper;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import org.dom4j.xpath.DefaultXPath;
import org.jaxen.VariableContext;
public class MakejdomWork {
public static void main(String[] args) {
new MakejdomWork().run();
}
public void run() {
ByteArrayInputStream bis = new ByteArrayInputStream("<abcde version=\"8.1\" xmlns=\"http://www.litle.com/schema\" response=\"0\" message=\"Valid Format\"> <response>000</response></abcde>".getBytes());
//ByteArrayInputStream bis = new ByteArrayInputStream("<abcde><response>000</response></abcde>".getBytes());
Map nsPrefixes = new HashMap();
nsPrefixes.put( "x", "http://www.litle.com/schema" );
DocumentFactory factory = new DocumentFactory();
factory.setXPathNamespaceURIs( nsPrefixes );
SAXReader reader = new SAXReader();
reader.setDocumentFactory( factory );
Document doc;
try {
doc = reader.read( bis );
Object value = doc.valueOf("/abcde/x:response");
System.out.println(value);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
Short answer: you need to use namespace prefixes if your parser is namespace aware (which dom4j is)

Resources