Errors
Error during migration generation:
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs".
at MissingDriverError.TypeORMError [as constructor] (D:\Projects\Mark1\api2\src\error\TypeORMError.ts:7:9)
at new MissingDriverError (D:\Projects\Mark1\api2\src\error\MissingDriverError.ts:8:9)
at DriverFactory.create (D:\Projects\Mark1\api2\src\driver\DriverFactory.ts:70:23)
at new Connection (D:\Projects\Mark1\api2\src\connection\Connection.ts:122:43)
at ConnectionManager.create (D:\Projects\Mark1\api2\src\connection\ConnectionManager.ts:61:28)
at D:\Projects\Mark1\api2\src\globals.ts:77:35
at step (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:143:27)
at Object.next (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:124:57)
at D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:117:75
at new Promise ()
ormConfig.ts
import { TypeOrmModuleOptions } from '#nestjs/typeorm';
import { join } from 'path';
require('dotenv').config();
class ConfigService {
constructor(private env: { [k: string]: string | undefined }) { }
private getValue(key: string, throwOnMissing = true): string {
const value = this.env[key];
if (!value && throwOnMissing) {
throw new Error(`config error - missing env.${key}`);
}
return value;
}
public ensureValues(keys: string[]) {
keys.forEach(k => this.getValue(k, true));
return this;
}
public getPort() {
return this.getValue('PORT', true);
}
public isProduction() {
const mode = this.getValue('MODE', false);
return mode != 'DEV';
}
public getTypeOrmConfig(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: this.getValue('POSTGRES_HOST'),
port: parseInt(this.getValue('POSTGRES_PORT')),
username: this.getValue('POSTGRES_USER'),
password: this.getValue('POSTGRES_PASSWORD'),
database: this.getValue('POSTGRES_DATABASE'),
entities: [join(__dirname, '**', '*.entity.{ts,js}')],
migrationsTableName: 'migration',
migrations: ['src/migration/*.ts'],
cli: {
migrationsDir: 'src/migration',
},
};
}
}
const configService = new ConfigService(process.env)
.ensureValues([
'POSTGRES_HOST',
'POSTGRES_PORT',
'POSTGRES_USER',
'POSTGRES_PASSWORD',
'POSTGRES_DATABASE'
]);
export = configService ;
appmodule.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import configService from 'ormConfig';
import { AppController } from './app.controller';
import { AppService } from './app.service';
#Module({
imports: [TypeOrmModule.forRoot(configService.getTypeOrmConfig())],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
.env file
POSTGRES_HOST=localhost
POSTGRES_PORT=8080
POSTGRES_USER=postgres
POSTGRES_PASSWORD=saad2113
POSTGRES_DATABASE=mark1
PORT=3000
MODE=DEV
RUN_MIGRATIONS=true
Related
Auth.service.ts
import { Injectable } from '#nestjs/common';
import { JwtService } from '#nestjs/jwt';
import { SearchUserOutput } from 'src/users/dto/search-user.output';
import { UsersService } from '../users/users.service';
#Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
async validateUser(username: string, password: string): Promise<SearchUserOutput> {
const user = await this.usersService.findOne(username);
if (user && user.password == password) {
const { password, ...result } = user;
return result;
}
return null;
}
async login(user: SearchUserOutput,role:string) {
return {
accessToken: this.jwtService.sign({
username: user.username,
role: role
}),
user,
};
}
}
Auth.resolver.ts
import { UseGuards } from '#nestjs/common';
import { Args, Context, Mutation, Resolver } from '#nestjs/graphql';
import { AuthService } from './auth.service';
import { LoginUserInput } from './dto/login-user.input';
import { LoginResponse } from './dto/login-response.ouput';
import { GqlAuthGuard } from './guards/gql-auth.guard';
#Resolver()
export class AuthResolver {
constructor(private authService: AuthService) {}
#Mutation(() => LoginResponse)
#UseGuards(GqlAuthGuard)
loginUser(
#Args('loginUserInput') loginUserInput: LoginUserInput,
#Context() context
): Promise<LoginResponse> {
return this.authService.login(context.user,'user');
}
}
Auth.module.ts
import { Module } from '#nestjs/common';
import { JwtModule } from '#nestjs/jwt';
import { MongooseModule } from '#nestjs/mongoose';
import { PassportModule } from '#nestjs/passport';
import { UserSchema } from 'src/users/entities/user.entity';
import { UsersModule } from 'src/users/users.module';
import { AuthResolver } from './auth.resolver';
import { AuthService } from './auth.service';
import { JwtStrategy } from './strategies/jwt.strategy';
import { LocalStrategy } from './strategies/local.strategy';
#Module({
imports: [PassportModule,UsersModule,JwtModule.register({
secret: 'secret',
signOptions: { expiresIn: '30d' },
}),MongooseModule.forFeature([{ name: 'User', schema: UserSchema }])],
providers: [AuthResolver, AuthService,LocalStrategy,JwtStrategy]
})
export class AuthModule {}
local.strategy.ts
import { Injectable, UnauthorizedException } from '#nestjs/common';
import { PassportStrategy } from '#nestjs/passport';
import { AuthService } from '../auth.service';
import { Strategy } from 'passport-local';
import { SearchUserOutput } from 'src/users/dto/search-user.output';
#Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private authService: AuthService) {
super();
}
async validate(username: string, password: string): Promise<SearchUserOutput> {
const user = await this.authService.validateUser(username, password);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
gql-authh.guard.ts
import { ExecutionContext, Injectable } from '#nestjs/common';
import { GqlExecutionContext } from '#nestjs/graphql';
import { AuthGuard } from '#nestjs/passport';
#Injectable()
export class GqlAuthGuard extends AuthGuard('local') {
constructor() {
super();
}
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext();
request.body = ctx.getArgs().loginUserInput;
return request;
}
}
login-response.output.ts
import { Field, ObjectType } from '#nestjs/graphql';
import { SearchUserOutput } from 'src/users/dto/search-user.output';
#ObjectType()
export class LoginResponse {
#Field(() => String)
accessToken: string;
#Field(() => SearchUserOutput)
user: SearchUserOutput;
}
login-user.input.ts
import { Field, InputType } from '#nestjs/graphql';
import { IsNotEmpty, IsString } from 'class-validator';
#InputType()
export class LoginUserInput {
#Field(() => String)
#IsNotEmpty()
#IsString()
username: string;
#Field(() => String)
#IsNotEmpty()
#IsString()
password: string;
}
it consistently giving me error
if you want source code then i will send you
"dependencies": {
"#nestjs/apollo": "^10.0.19",
"#nestjs/common": "^9.0.0",
"#nestjs/core": "^9.0.0",
"#nestjs/graphql": "^10.0.21",
"#nestjs/jwt": "^9.0.0",
"#nestjs/mapped-types": "*",
"#nestjs/mongoose": "^9.2.0",
"#nestjs/passport": "^9.0.0",
"#nestjs/platform-express": "^9.0.0",
"#nestjs/testing": "^9.0.11",
"#types/jest": "^28.1.7",
"#types/node": "^18.7.6",
"#types/passport-jwt": "^3.0.6",
"apollo-server-express": "^3.10.1",
"class-validator": "^0.13.2",
"express": "^4.18.1",
"graphql": "^15",
"mongoose": "^6.5.2",
"passport": "^0.6.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"type-graphql": "^1.1.1",
"webpack": "^5.74.0"
},
"devDependencies": {
"#types/express": "^4.17.13",
"#types/passport-local": "^1.0.34",
"#types/supertest": "^2.0.11",
"#typescript-eslint/eslint-plugin": "^5.0.0",
"#typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.2",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "28.0.5",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.0.0",
"typescript": "^4.3.5"
},
This is what my auth.module.ts looks like:
import { Module } from "#nestjs/common";
import { ConfigModule, ConfigService } from "#nestjs/config";
import { JwtModule } from "#nestjs/jwt";
import { PassportModule } from "#nestjs/passport";
import { TypeOrmModule } from "#nestjs/typeorm";
import appConfig from "src/config/app.config";
import devConfig from "src/config/dev.config";
import stagConfig from "src/config/stag.config";
import { User } from "src/entities/entity/user.entity";
import { AuthService } from "./auth.service";
import { JwtStrategy } from "./passport-strategies/jwt-strategy";
import { LocalStrategy } from "./passport-strategies/local-strategy";
#Module({
imports: [
PassportModule,
ConfigModule.forRoot({
load: [appConfig, devConfig, stagConfig],
ignoreEnvFile: true,
isGlobal: true,
}),
TypeOrmModule.forFeature([
User
]),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
// secret: configService.get<string>('jwt.secret'),
secret: process.env.TOKEN_KEY,
signOptions: { expiresIn: 30 }
}),
inject: [ConfigService]
}),
],
providers: [
AuthService,
LocalStrategy,
JwtStrategy
],
exports: [AuthService],
})
export class AuthModule {}
As you can see I have set signOptions: { expiresIn: 30 } but when I analyze the token it has no expiration parameter and does not expire.
I am using https://jwt.io/#encoded-jwt to analyze the token:
You have to pass the expiresIn value as string and mention s for seconds like this
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
Do let me know if this works!
The same problem. search ignoreExpiration flag. Here's my problem
e:
#Injectable()
export class JWTStrategy extends PassportStrategy(Strategy) {
constructor(
readonly configService: ConfigService,
private userService: UserService,
) {
super({
jwtFromRequest: ExtractJwt.fromHeader(
configService.get('API_ACCESS_TOKEN_HEADER'),
),
ignoreExpiration: true, // *** FIXME: here
secretOrKey: configService.get('API_ACCESS_TOKEN_SECRET'),
});
}
...
Here is type:
export interface StrategyOptions {
secretOrKey?: string | Buffer | undefined;
secretOrKeyProvider?: SecretOrKeyProvider | undefined;
jwtFromRequest: JwtFromRequestFunction;
issuer?: string | undefined;
audience?: string | undefined;
algorithms?: string[] | undefined;
ignoreExpiration?: boolean | undefined;
passReqToCallback?: boolean | undefined;
jsonWebTokenOptions?: VerifyOptions | undefined;
}
The ignoreExpiration used, https://github.com/auth0/node-jsonwebtoken/blob/master/verify.js#L147
Hope it will help you
im getting this error Cannot return null for non-nullable field CityBoundaries.city_name. from mongoDB, but if im using static json data, i get my response fine. Here's my code. Any help will be appreciated :)
city-boundries.model.ts
import { ObjectType, Field, ID, Int, Float } from '#nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import 'dotenv/config';
import { CityBoundiresFeatures } from 'src/types/city-boundries-features';
import mongoose from 'mongoose';
export type CityBoundriesDocument = CityBoundaries & Document;
#Schema()
#ObjectType()
export class CityBoundaries extends Document {
#Field(() => ID, { nullable: true })
_id: string | number;
#Prop()
#Field()
readonly city_admin_level: number;
#Prop({ required: true })
#Field()
readonly city_name: string;
#Prop({ required: true })
#Field(() => Float)
readonly city_id: number;
#Prop({ required: true })
#Field(() => Float)
readonly city_osm_id: number;
#Prop({
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'CityBoundiresFeatures',
})
#Field(() => [CityBoundiresFeatures], { nullable: true })
features: CityBoundiresFeatures[];
#Prop({ required: true })
#Field({ nullable: true })
type: string;
}
export const CityBoundriesSchema = SchemaFactory.createForClass(CityBoundaries);
city-boundries.module.ts
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesSchema,
} from 'src/models/city-boundries.model';
import { CityBoundriesService } from 'src/services/city-boundries.service';
import { CityBoundriesResolvers } from 'src/resolvers/city-boundries.resolver';
import { Bop500_City, CitiesSchema } from 'src/models/cities.model';
import { CitiesService } from 'src/services/cities.service';
#Module({
imports: [
MongooseModule.forFeature([
{
name: CityBoundaries.name,
schema: CityBoundriesSchema,
},
{ name: Bop500_City.name, schema: CitiesSchema },
]),
],
providers: [CityBoundriesService, CityBoundriesResolvers, CitiesService],
})
export class CityBoundriesModule {}
cities.resolver.ts
import { Resolver, Query, Args, ResolveField, Parent } from '#nestjs/graphql';
import { Bop500_City } from 'src/models/cities.model';
import { CityBoundaries } from 'src/models/city-boundries.model';
import { CitiesService } from 'src/services/cities.service';
import { CityBoundriesService } from 'src/services/city-boundries.service';
#Resolver(() => Bop500_City)
export class CitiesResolvers {
constructor(
private readonly citiesService: CitiesService,
private readonly cityBoundariesService: CityBoundriesService,
) {}
#Query(() => [Bop500_City])
/**
* #returns list of all cities
*/
async getAllCities() {
return this.citiesService.findMany();
}
#Query(() => [Bop500_City], { nullable: true })
/**
* #param {string} value take city name as argument from user
* #returns detail of city
*/
async getCity(#Args('city') value: string) {
const res = await this.citiesService.findOneByName(value);
console.log('Response: ', res);
return res;
}
#ResolveField(() => CityBoundaries)
async getBoundries(#Parent() parent: Bop500_City) {
const res = await this.cityBoundariesService.findOneByCityName(
parent.city_name,
);
console.log('Response: ', res);
return res;
}
}
city-boundries.service.ts
import { Injectable } from '#nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesDocument,
} from 'src/models/city-boundries.model';
import * as cityBoundriesData from '../static/City_boundaries.json';
#Injectable()
export class CityBoundriesService {
constructor(
#InjectModel(CityBoundaries.name)
private cityBoundriesModel: Model<CityBoundriesDocument>,
) {}
/**
* #param {string} cityName take city name as argument from user
* #returns boundries of city
*/
async findOneByCityName(cityName: string) {
const res = await this.cityBoundriesModel.find({ city_name: cityName });
return res;
}
}
app.module.ts
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '#nestjs/apollo';
import { MongooseModule } from '#nestjs/mongoose';
import { CitiesModule } from './module/cities.module';
import 'dotenv/config';
import { CityBoundriesModule } from './module/city-boundries.module';
#Module({
imports: [
MongooseModule.forRoot(process.env.MONGODB_DB_URI, {
dbName: process.env.DB_NAME,
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'src/schema/schema.gql',
introspection: true,
playground: true,
}),
CitiesModule,
CityBoundriesModule,
],
})
export class AppModule {}
I'm having a problem with Nest Js and mongoose, Im trying to make a seed for my database,
And the main problem I'm having is I cannot import service from my module, into other module.
And it constantly gives me error:
Nest can't resolve dependencies of the CategoryModel (?). Please make sure that the argument at index [0] is available in the MongooseModule context.
the main thing I'm trying to do is to create seed for my categories.
Here is my Category Module:
import { Module } from '#nestjs/common';
import { CategoryController } from './category.controller';
import { CategoryService } from './category.service';
import { MongooseModule } from '#nestjs/mongoose';
import { CategorySchema } from 'src/models/category.schema';
#Module({
imports: [MongooseModule.forFeature([{ name: 'Category', schema: CategorySchema }])],
controllers: [CategoryController],
providers: [CategoryService]
})
export class CategoryModule {}
My Category service:
import { Model } from 'mongoose';
import { Injectable, Inject } from '#nestjs/common';
import { CategoryInterface } from '../interfaces/category.interface';
import { InjectModel } from '#nestjs/mongoose';
#Injectable()
export class CategoryService {
constructor(#InjectModel('Category') private categoryModel: Model<CategoryInterface>) {}
async create(category){
const createdQuestion = new this.categoryModel(category);
return createdQuestion.save();
}
async getMainCategories() {
return this.categoryModel.find( { parent: null } );
}
}
My Category Controller:
import { Controller, Post, Get, Body, HttpCode } from '#nestjs/common';
import { CategoryService } from './category.service';
#Controller('category')
export class CategoryController {
constructor(private categoryService: CategoryService) { }
#Post()
#HttpCode(204)
async createCategory(#Body() category) {
console.log('evo je kategorija ', category);
const data = await this.categoryService.create(category);
}
#Get('/main')
async getAllCategories() {
const data = await this.categoryService.getMainCategories();
return data;
}
}
My Seeder module where I'm having provider that seed database:
import { Module } from '#nestjs/common';
import { Seeder } from './seeder';
#Module({
providers: [Seeder],
})
export class SeederModule {}
and my seeder.ts
import { Injectable } from '#nestjs/common';
import { CategoryService } from 'src/category/category.service';
#Injectable()
export class Seeder {
constructor(private categoryService: CategoryService) { }
async seed() {
}
async categories() {
// const data = await this.categoryService.createMultiple(categories);
}
}
My App.module
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CategoryModule } from './category/category.module';
import { QuizModule } from './quiz/quiz.module';
import { ConfigModule } from '#nestjs/config';
import config from './config/config';
#Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017'),
ConfigModule.forRoot({ load: [config], isGlobal: true }),
CategoryModule,
QuizModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Category Model:
import * as mongoose from 'mongoose';
export const CategorySchema = new mongoose.Schema({
name: { type:String, required:true, unique: true },
slug: { type:String, required:true, unique: true },
});
And for some reason it is not working, even If I import whole
GitHub Repository of Project: https://github.com/HunterJS-bit/react-quiz-app
CategoryModule, or CategoryService into Seeder.module ??
Note: To reproduce error try running npm run seed from
server/package.json
Thanks for the help :)
You need to have the CategoryModule add exports: [CategoryService] to allow for other modules to import the module and make use to the CategoryService. This is how you share providers in NestJS. The, you need to add imports: [CategoryModule] to the SeederModule to allow the providers of the SeederModule to use the exports of the CategoryModule. Then, everything should load up just fine.
I have this ionic 4 project (Using REST API) and have also install ionic native storage. I might have multiple questions concerning this project, but the first is:
I want to store login data so I can be able to pass a token to the header to be used for other endpoints. But if I run the app and try to login, I get the following error:
Error storing item
Object { code: 5, source: "Native", exception: null, stack: "" }
My auth ts is where my login function is:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { tap } from 'rxjs/operators';
import { ApiService } from './api.service';
import { User } from '../models/user';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
#Injectable({
providedIn: 'root'
})
export class AuthService {
isLoggedIn = false;
token: any;
constructor(
private http: HttpClient,
private api: ApiService,
private storage: NativeStorage
) { }
login(account_number: Number, password: String) {
return this.http.post(this.api.API_URL + '/login',
{account_number: account_number, password: password}
).pipe(
tap(token => {
this.storage.setItem('token', token)
.then(
() => {
console.log('Token Stored', token);
},
error => console.error('Error storing item', error)
);
this.token = token;
this.isLoggedIn = true;
return token;
}),
);
}
register(name: String, email: String, phone: Number, reference: String, account_number: String, password: String) {
return this.http.post(this.api.API_URL + '/register',
{ name: name, email: email, phone: phone, reference: reference, account_number: account_number, password: password }
)
}
logout() {
const headers = new HttpHeaders({
'Authorization': "auth-token" + this.token
});
return this.http.get(this.api.API_URL + '/logout', { headers: headers })
.pipe(
tap(data => {
this.storage.remove("token");
this.isLoggedIn = false;
delete this.token;
return data;
})
)
}
getToken() {
return this.storage.getItem('token').then(
data => {
this.token = data;
if (this.token != null) {
this.isLoggedIn = true;
} else {
this.isLoggedIn = false;
}
},
error => {
this.token = null;
this.isLoggedIn = false;
}
);
}
}
And here is is my login.ts.
import { Component, OnInit } from '#angular/core';
import { ModalController, NavController } from '#ionic/angular';
import { AuthService } from 'src/app/services/auth.service';
import { AlertService } from 'src/app/services/alert.service';
import { RegisterPage } from '../register/register.page';
import { NgForm } from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
userdata: any;
constructor(
private modalC: ModalController,
private authService: AuthService,
private navCtrl: NavController,
private alertService: AlertService,
// private router: Router
) { }
ngOnInit() {
}
// Dismiss Login Modal
dismissLogin() {
this.modalC.dismiss();
}
// On Register button tap, dismiss login modal and open register modal
async registerModal() {
this.dismissLogin();
const registerModal = await this.modalC.create({
component: RegisterPage
});
return await registerModal.present();
}
login(form: NgForm) {
this.authService.login(form.value.account_number, form.value.password).subscribe(
data => {
this.userdata = data;
this.alertService.presentToast("Logged In");
console.log('this is loggin in userdata', data, "and this is the stored auth-token", this.userdata.message);
},
error => {
console.log(error, "logged in");
},
() => {
this.dismissLogin();
this.navCtrl.navigateRoot('/dashboard');
console.log('this is this.userdata', )
}
);
}
}
Here is aslo my app.module.ts
import { NgModule, ErrorHandler } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { IonicModule, IonicRouteStrategy, } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '#angular/common/http';
import { NativeStorage } from '#ionic-native/native-storage/ngx';
#NgModule({
declarations: [
AppComponent,],
entryComponents: [
],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule
],
providers: [
StatusBar,
SplashScreen,
NativeStorage,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
You can simply use javascript local storage and also use Ionic native storge for your purpose.
Mostly is used localStorage.set(). In case just want to store strings.
u also use Ionic native storage for the object and many things.
https://ionicframework.com/docs/native/native-storage