.png)
%20(1).png)
/users/123){ "id": 1, "name": "Alice" }).onous operations allow this data fetching to happen without freezing the rest of your application.GET /posts: Fetch all blog posts.GET /posts/1: Fetch the post with ID 1.POST /posts: Create a new post.{
"id": 1,
"title": "REST Basics",
"author": "Alice",
"content": "A deep dive into REST principles."
}/users/123returns all user fields, even if the client only needsname and email ./users/123/postsis required./v1, /v2 endpoints.User, Post).query GetUser {
user(id: "123") {
name
email
}
}name and email.query GetUserWithPosts {
user(id: "123") {
name
posts {
title
comments(limit: 3) {
text
}
}
}
}GET /users/123 → Fetch user data.GET /users/123/posts?limit=3 → Fetch posts.query {
user(id: "123") {
name
posts(limit: 3) {
title
}
}
}.webp)
/users/123returns all user fields, even if the client only needsname and email ./users/123/postsis required./v1, /v2 endpoints.type User {
id: ID!
name: String!
email: String!
posts: [Post!]! # One-to-many relationship
}
type Post {
id: ID!
title: String!
content: String!
author: User! # Back-reference to User
}
type Query {
user(id: ID!): User
post(id: ID!): Post
}# Avoid
user(id: "123") {
posts {
comments {
author {
posts { ... }
}
}
}
}type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
}
query GetPosts {
posts(first: 10, after: "cursor") {
edges { node { title } }
pageInfo { endCursor, hasNextPage }
}
}type User {
age: Int @deprecated(reason: "Use birthdate instead.")
birthdate: String!
}const { data, loading } = useQuery(GET_USER, { variables: { id: "123" } });
const [createPost] = useMutation(CREATE_POST);const GET_LOCAL_STATE = gql`
query GetTheme {
theme @client # Fetch from Apollo Cache
}
`;const UserComponent = ({ user }) => {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
avatar
}
`,
user
);
return <div>{data.name}</div>;
};const UserComponent = ({ user }) => {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
avatar
}
`,
user
);
return <div>{data.name}</div>;
};
const { data, loading } = useQuery(GET_USER, { variables: { id: "123" } });
const [createPost] = useMutation(CREATE_POST);const userLoader = new DataLoader(async (ids) => {
const users = await db.users.find({ id: { $in: ids } });
return ids.map(id => users.find(u => u.id === id));
});
// Resolver
User: {
posts: (user) => postLoader.load(user.id),
}const resolvers = {
User: {
email: (user, args, context) => {
if (context.role !== "admin") return null;
return user.email;
}
}
};const userLoader = new DataLoader(async (ids) => {
const users = await db.users.find({ id: { $in: ids } });
return ids.map(id => users.find(u => u.id === id));
});
// Resolver
User: {
posts: (user) => postLoader.load(user.id),
}const resolvers = {
Query: {
user: async (_, { id }) => {
const res = await fetch(`https://legacy-api.com/users/${id}`);
return res.json();
}
}
};type Query {
userWithOrders(id: ID!) {
user: User # From User Service
orders: [Order!]! # From Order Service
}
}# Users Service
type User @key(fields: "id") {
id: ID!
name: String!
}
# Posts Service
type Post @key(fields: "id") {
id: ID!
author: User @provides(fields: "name")
}# codegen.yml
generates:
src/types.ts:
plugins:
- typescript
- typescript-resolvers











%20(1).png)
Geospatial data is becoming increasingly important in a variety of applications, from mapping and navigation to location-based services and geospatial analytics. MongoDB, with its support for geospatial indexes and queries, provides an excellent platform for storing and querying geographical data. In this article, we’ll dive into MongoDB’s geospatial features and show how you can leverage them with Node.js.
Before we explore the queries, we need to populate our MongoDB collection with geospatial data. I have uploaded the necessary JSON files: sl-places.json and sl-areas.json to my GitHub repository. These files contain geographical data for various places and areas in Sri Lanka, respectively.
First, let’s write a seeder script to load this data into MongoDB. You can find the full code in My repository:
const fs = require("fs");
const { getDB, closeDB } = require("./db");
(async () => {
const initialSLPlaces = JSON.parse(
fs.readFileSync("sl-places.json", "utf-8")
);
const initialSLAreas = JSON.parse(fs.readFileSync("sl-areas.json", "utf-8"));
const db = await getDB();
// Delete existing records to avoid duplication
await db.collection("sl-places").deleteMany();
// Insert new data into the collection
await db
.collection("sl-places")
.insertMany([...initialSLPlaces, ...initialSLAreas]);
// Create a 2dsphere index to enable efficient geospatial queries
await db.collection("sl-places").createIndex({ location: "2dsphere" });
// Close the database connection
closeDB();
})();sl-places.json and sl-areas.json into the sl-places collection.location field to enable efficient geospatial queries.Indexes are critical for improving the performance of database queries, especially when dealing with large datasets. In the context of geospatial data, MongoDB uses 2dsphere indexes to support queries that deal with spherical geometry, such as finding points within a certain distance from a location or finding points within a polygon.
Without a 2dsphere index on the location field, geospatial queries would be much slower, as MongoDB would need to scan every document in the collection to perform the query. By creating a 2dsphere index, MongoDB can efficiently query geospatial data by using the index to quickly find relevant documents based on their geographic location.
One of the most common geospatial queries is finding places that are near a specific location. In MongoDB, we can use the $near operator to perform this search. The following Node.js code demonstrates how to search for places within 500 meters of Kirinda Beach (coordinates: [81.2570, 6.2155]).
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
// Search near Kirinda Beach within 500m
const places = await db
.collection("sl-places")
.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [81.2570, 6.2155], // Coordinates for Kirinda Beach
},
$maxDistance: 500, // Max distance in meters
},
},
})
.toArray();
console.log(places); // Display the found places
closeDB(); // Close the database connection
})();$near operator finds documents within a specified distance from a point. In this case, we are searching for places within 500 meters of the given coordinates.This query is ideal for applications that need to find nearby places, such as a location-based service for tourists, or a navigation app that shows nearby points of interest.
In addition to searching near a location, MongoDB allows you to search for places within a specific geographic area defined by a polygon. This can be useful for querying places that lie within a predefined region or boundary.
The following example demonstrates how to search for places within a rectangular polygon defined by four corners:
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
const places = await db
.collection("sl-places")
.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [
[
[81.2, 6.2], // Bottom-left corner
[81.6, 6.2], // Bottom-right corner
[81.6, 6.5], // Top-right corner
[81.2, 6.5], // Top-left corner
[81.2, 6.2], // Closing the polygon
],
],
},
},
},
})
.toArray();
console.log(places); // Display places within the polygon
closeDB(); // Close the database connection
})();$geoWithin operator is used to find documents within a specified geometry, which can be a polygon, circle, or other shapes.This query is particularly useful for applications that need to filter results within a geographical region, such as finding all points of interest within a park, city, or administrative region.
Another geospatial operator in MongoDB is $geoIntersects, which allows you to search for areas that intersect with a specific point. This is useful for cases where you need to find out which regions or zones contain a given location.
Below is an example of how to search for areas that intersect with the point [81.7302, 7.2801]:
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB("playground");
const area = await db
.collection("sl-places")
.find({
area: {
$geoIntersects: {
$geometry: { type: "Point", coordinates: [81.7302, 7.2801] },
},
},
})
.toArray();
console.log(area); // Display areas that intersect with the point
closeDB(); // Close the database connection
})();$geoIntersects operator finds documents whose geometry intersects with the specified geometry.This query can be used to determine which administrative regions or zoning areas intersect with a given point, such as determining which district a particular location belongs to.
MongoDB’s geospatial capabilities make it an excellent choice for applications that deal with location-based data. By using the 2dsphere index and geospatial operators like $near, $geoWithin, and $geoIntersects, developers can build powerful, location-aware applications.
In this article, we’ve demonstrated how to perform basic geospatial queries with MongoDB and Node.js. We also covered the importance of creating a 2dsphere index, which is crucial for ensuring fast and efficient geospatial queries on large datasets.
By integrating MongoDB’s geospatial queries into your application, you can create more intelligent, context-aware experiences for your users.
// Checkout complete code in GitHub, Don’t forget to give me a star :)
%20(1).png)
Geospatial data is becoming increasingly important in a variety of applications, from mapping and navigation to location-based services and geospatial analytics. MongoDB, with its support for geospatial indexes and queries, provides an excellent platform for storing and querying geographical data. In this article, we’ll dive into MongoDB’s geospatial features and show how you can leverage them with Node.js.
Before we explore the queries, we need to populate our MongoDB collection with geospatial data. I have uploaded the necessary JSON files: sl-places.json and sl-areas.json to my GitHub repository. These files contain geographical data for various places and areas in Sri Lanka, respectively.
First, let’s write a seeder script to load this data into MongoDB. You can find the full code in My repository:
const fs = require("fs");
const { getDB, closeDB } = require("./db");
(async () => {
const initialSLPlaces = JSON.parse(
fs.readFileSync("sl-places.json", "utf-8")
);
const initialSLAreas = JSON.parse(fs.readFileSync("sl-areas.json", "utf-8"));
const db = await getDB();
// Delete existing records to avoid duplication
await db.collection("sl-places").deleteMany();
// Insert new data into the collection
await db
.collection("sl-places")
.insertMany([...initialSLPlaces, ...initialSLAreas]);
// Create a 2dsphere index to enable efficient geospatial queries
await db.collection("sl-places").createIndex({ location: "2dsphere" });
// Close the database connection
closeDB();
})();sl-places.json and sl-areas.json into the sl-places collection.location field to enable efficient geospatial queries.Indexes are critical for improving the performance of database queries, especially when dealing with large datasets. In the context of geospatial data, MongoDB uses 2dsphere indexes to support queries that deal with spherical geometry, such as finding points within a certain distance from a location or finding points within a polygon.
Without a 2dsphere index on the location field, geospatial queries would be much slower, as MongoDB would need to scan every document in the collection to perform the query. By creating a 2dsphere index, MongoDB can efficiently query geospatial data by using the index to quickly find relevant documents based on their geographic location.
One of the most common geospatial queries is finding places that are near a specific location. In MongoDB, we can use the $near operator to perform this search. The following Node.js code demonstrates how to search for places within 500 meters of Kirinda Beach (coordinates: [81.2570, 6.2155]).
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
// Search near Kirinda Beach within 500m
const places = await db
.collection("sl-places")
.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [81.2570, 6.2155], // Coordinates for Kirinda Beach
},
$maxDistance: 500, // Max distance in meters
},
},
})
.toArray();
console.log(places); // Display the found places
closeDB(); // Close the database connection
})();$near operator finds documents within a specified distance from a point. In this case, we are searching for places within 500 meters of the given coordinates.This query is ideal for applications that need to find nearby places, such as a location-based service for tourists, or a navigation app that shows nearby points of interest.
In addition to searching near a location, MongoDB allows you to search for places within a specific geographic area defined by a polygon. This can be useful for querying places that lie within a predefined region or boundary.
The following example demonstrates how to search for places within a rectangular polygon defined by four corners:
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
const places = await db
.collection("sl-places")
.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [
[
[81.2, 6.2], // Bottom-left corner
[81.6, 6.2], // Bottom-right corner
[81.6, 6.5], // Top-right corner
[81.2, 6.5], // Top-left corner
[81.2, 6.2], // Closing the polygon
],
],
},
},
},
})
.toArray();
console.log(places); // Display places within the polygon
closeDB(); // Close the database connection
})();$geoWithin operator is used to find documents within a specified geometry, which can be a polygon, circle, or other shapes.This query is particularly useful for applications that need to filter results within a geographical region, such as finding all points of interest within a park, city, or administrative region.
Another geospatial operator in MongoDB is $geoIntersects, which allows you to search for areas that intersect with a specific point. This is useful for cases where you need to find out which regions or zones contain a given location.
Below is an example of how to search for areas that intersect with the point [81.7302, 7.2801]:
const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB("playground");
const area = await db
.collection("sl-places")
.find({
area: {
$geoIntersects: {
$geometry: { type: "Point", coordinates: [81.7302, 7.2801] },
},
},
})
.toArray();
console.log(area); // Display areas that intersect with the point
closeDB(); // Close the database connection
})();$geoIntersects operator finds documents whose geometry intersects with the specified geometry.This query can be used to determine which administrative regions or zoning areas intersect with a given point, such as determining which district a particular location belongs to.
MongoDB’s geospatial capabilities make it an excellent choice for applications that deal with location-based data. By using the 2dsphere index and geospatial operators like $near, $geoWithin, and $geoIntersects, developers can build powerful, location-aware applications.
In this article, we’ve demonstrated how to perform basic geospatial queries with MongoDB and Node.js. We also covered the importance of creating a 2dsphere index, which is crucial for ensuring fast and efficient geospatial queries on large datasets.
By integrating MongoDB’s geospatial queries into your application, you can create more intelligent, context-aware experiences for your users.
// Checkout complete code in GitHub, Don’t forget to give me a star :)








sl-places.json and sl-areas.json to my GitHub repository. These files contain geographical data for various places and areas in Sri Lanka, respectively.First, let’s write a seeder script to load this data into MongoDB. You can find the full code in My repository:const fs = require("fs");
const { getDB, closeDB } = require("./db");
(async () => {
const initialSLPlaces = JSON.parse(
fs.readFileSync("sl-places.json", "utf-8")
);
const initialSLAreas = JSON.parse(fs.readFileSync("sl-areas.json", "utf-8"));
const db = await getDB();
// Delete existing records to avoid duplication
await db.collection("sl-places").deleteMany();
// Insert new data into the collection
await db
.collection("sl-places")
.insertMany([...initialSLPlaces, ...initialSLAreas]);
// Create a 2dsphere index to enable efficient geospatial queries
await db.collection("sl-places").createIndex({ location: "2dsphere" });
// Close the database connection
closeDB();
})();sl-places.json and sl-areas.json into the sl-places collection.location field to enable efficient geospatial queries.location field, geospatial queries would be much slower, as MongoDB would need to scan every document in the collection to perform the query. By creating a 2dsphere index, MongoDB can efficiently query geospatial data by using the index to quickly find relevant documents based on their geographic location.$near operator to perform this search. The following Node.js code demonstrates how to search for places within 500 meters of Kirinda Beach (coordinates: [81.2570, 6.2155]).const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
// Search near Kirinda Beach within 500m
const places = await db
.collection("sl-places")
.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [81.2570, 6.2155], // Coordinates for Kirinda Beach
},
$maxDistance: 500, // Max distance in meters
},
},
})
.toArray();
console.log(places); // Display the found places
closeDB(); // Close the database connection
})();$near operator finds documents within a specified distance from a point. In this case, we are searching for places within 500 meters of the given coordinates.const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB();
const places = await db
.collection("sl-places")
.find({
location: {
$geoWithin: {
$geometry: {
type: "Polygon",
coordinates: [
[
[81.2, 6.2], // Bottom-left corner
[81.6, 6.2], // Bottom-right corner
[81.6, 6.5], // Top-right corner
[81.2, 6.5], // Top-left corner
[81.2, 6.2], // Closing the polygon
],
],
},
},
},
})
.toArray();
console.log(places); // Display places within the polygon
closeDB(); // Close the database connection
})();$geoWithin operator is used to find documents within a specified geometry, which can be a polygon, circle, or other shapes.[81.7302, 7.2801]:const { getDB, closeDB } = require("./db");
(async () => {
const db = await getDB("playground");
const area = await db
.collection("sl-places")
.find({
area: {
$geoIntersects: {
$geometry: { type: "Point", coordinates: [81.7302, 7.2801] },
},
},
})
.toArray();
console.log(area); // Display areas that intersect with the point
closeDB(); // Close the database connection
})();$geoIntersects operator finds documents whose geometry intersects with the specified geometry.$near, $geoWithin, and $geoIntersects, developers can build powerful, location-aware applications.npx @react-native-community/cli@latest init exampleProject
android directory of the project,I navigated to the java/com/exampleproject folder and created a new Kotlin class, CounterModule.kt. Below is the implementation:package com.exampleproject
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.Promise
class CounterModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
private var counter = 0
override fun getName(): String {
// The name we can access inside native modules
return "Counter"
}
// Expose increment method
@ReactMethod
fun increment(callback: Callback) {
counter++
// Call the callback with the updated counter value
callback.invoke(counter)
}
// Expose decrement method as a Promise
@ReactMethod
fun decrement(promise: Promise) {
if (counter > 0) {
counter--
promise.resolve(counter) // Resolve the promise with the updated counter value
} else {
promise.reject("COUNTER_ERROR", "Counter value cannot be less than 0")
}
}
}CounterModule class that includes two methods:increment: Increases the counter value and returns it via a callback.decrement: Decreases the counter value if it is greater than 0 and resolves it as a promise. If the counter is already at 0, it rejects the promise with an error.package com.exampleproject
import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
// Module register import
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager
// Extend ReactPackage to register module
class CounterPackage : ReactPackage {
override fun createNativeModules(
reactContext: ReactApplicationContext
): MutableList<NativeModule> = listOf(CounterModule(reactContext)).toMutableList()
override fun createViewManagers(
reactContext: ReactApplicationContext
): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
}override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
add(CounterPackage())
}// Counter.swift
// exampleProject
import Foundation
// This to make sure to export these class/function to object c runtime
@objc(Counter)
class CounterModule: NSObject {
private var count = 0
// _ is to get the first param, callback to get the second param
@objc
func increment(_ callback: RCTResponseSenderBlock) {
count += 1
// print(count);
callback([count])
}
@objc
func decrement(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
if count == 0 {
let error = NSError(domain: "Counter", code: 200, userInfo: nil)
reject("ERROR_COUNT", "count cannot be negative", error)
} else {
count -= 1
resolve(count)
}
}
// This means we are asking React Native to initialize these modules before the JS main thread starts executing
// If returns false, this means it's okay if we initialize the module in the background thread
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
}increment: Increases the counter and returns the new value to JavaScript via a callback.decrement: Decreases the counter, returning a promise to resolve the new value or reject it with an error if the counter is already 0.Counter.m file in the iOS project:// Counter.m
// exampleProject
#import <Foundation/Foundation.h>
// This will help us export the function to React Native
#import "React/RCTBridgeModule.h"
// Expose the Counter object
@interface RCT_EXTERN_MODULE(Counter, NSObject)
// Expose increment method
RCT_EXTERN_METHOD(increment : (RCTResponseSenderBlock)callback)
// Expose decrement promise
RCT_EXTERN_METHOD(decrement : (RCTPromiseResolveBlock)resolve
reject : (RCTPromiseRejectBlock)reject)
@endimport { NativeModules } from 'react-native';
const { Counter } = NativeModules;
// Increment the counter
Counter.increment((newCounterValue) => {
console.log(`Counter incremented: ${newCounterValue}`);
});
// Decrement the counter
Counter.decrement()
.then((newCounterValue) => {
console.log(`Counter decremented: ${newCounterValue}`);
})
.catch((error) => {
console.error(`Error: ${error.message}`);
});








// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}// Add the below header at the top of the file
#import <React/RCTLinkingManager.h>
// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
npx @react-native-community/cli@latest init exampleProjectpackage com.exampleproject
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Callback
import com.facebook.react.bridge.Promise
class CounterModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
private var counter = 0
override fun getName(): String {
// The name we can access inside native modules
return "Counter"
}
// Expose increment method
@ReactMethod
fun increment(callback: Callback) {
counter++
// Call the callback with the updated counter value
callback.invoke(counter)
}
// Expose decrement method as a Promise
@ReactMethod
fun decrement(promise: Promise) {
if (counter > 0) {
counter--
promise.resolve(counter) // Resolve the promise with the updated counter value
} else {
promise.reject("COUNTER_ERROR", "Counter value cannot be less than 0")
}
}
}CounterModule class that includes two methods:increment: Increases the counter value and returns it via a callback.decrement: Decreases the counter value if it is greater than 0 and resolves it as a promise. If the counter is already at 0, it rejects the promise with an error.npx @react-native-community/cli@latest init exampleProject




.webp)
import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
assert driver.getTitle().contains("Example Domain");
driver.quit() pipeline {
stages {
stage('Test') {
steps {
sh 'pytest tests/'
}
}
}
}import pytest
@pytest.mark.parametrize("username,password", [("user1", "pass1"), ("user2", "pass2")])
def test_login(username, password):
assert login(username, password) == "Success"fake = Faker()
print(fake.email())

@prisma/adapter-pg and AWS Secrets Manager on the NestJS project.Additionally, we’ll explore deployment considerations, including handling Prisma migrations and seed operations during the build and deploy stages, ensuring that your application runs smoothly in production.@prisma/adapter-pg: Allows integration with the pg library, giving fine-grained control over connection pooling.pg's connection pooling capabilities to dynamically fetch credentials and manage connections.@prisma/adapter-pg adapter and support dynamic connection management.npm install @prisma/adapter-pg @aws-sdk/client-secrets-manager pgdriverAdapters preview feature in schema.prisma:generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}npx prisma generate
import { Injectable } from '@nestjs/common';
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
@Injectable()
export class SecretsService {
private secretsManagerClient: SecretsManagerClient;
constructor() {
this.secretsManagerClient = new SecretsManagerClient({
region: 'YOUR_AWS_REGION',
});
}
// Fetch database URL from AWS Secrets Manager
async getDatabaseUrl(): Promise<string> {
try {
const secretId = 'YOUR_AWS_SECRET_ID';
const command = new GetSecretValueCommand({ SecretId: secretId });
const secret = await this.secretsManagerClient.send(command);
if (!secret.SecretString) {
throw new Error('SecretString is empty');
}
const credentials = JSON.parse(secret.SecretString);
return credentials.password;
} catch (error) {
throw error;
}
}
}import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import { SecretsService } from '../secrets/secrets.service';
import { Pool } from 'pg';
@Injectable()
export class DatabaseService extends PrismaClient implements OnModuleInit {
private pool: Pool;
constructor(
private readonly secretsService: SecretsService,
) {
// Dynamically fetch the password and set up the pg Pool
const pool = new Pool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
database: process.env.DB_NAME,
port: 5432,
password: async () => {
return await this.secretsService.getDatabaseUrl();
},
ssl: { rejectUnauthorized: false },
});
const adapter = new PrismaPg(pool);
super({ adapter });
}
// Connect to the database
async onModuleInit() {
try {
await this.$connect();
} catch (error) {
throw error;
}
}
// Close the database connection pool when the application shuts down
async onModuleDestroy() {
try {
await this.pool.end();
} catch (error) {
throw error;
}
}
}ssl: { rejectUnauthorized: false }?rejectUnauthorized option determines whether the client verifies the database server's SSL certificate. By setting rejectUnauthorized: false, the client skips this validation, which can be helpful during local development or testing when certificates might not be properly configured. However, in production, it's better to ensure secure communication by using properly configured SSL certificates and enabling rejectUnauthorized: true. This prevents man-in-the-middle attacks and ensures the authenticity of the database server.rejectUnauthorized is set to falseSecretsService ensures the latest credentials are always fetched.pg's Pool ensures connections finish gracefully before new credentials are used.pg's pooling.DATABASE_URL="postgresql://user:$(encodeURIComponent 'password')@host:5432/dbname"
@prisma/adapter-pg with AWS Secrets Manager and pg, we solved the challenge of dynamic database credential rotation in Prisma. This approach ensures high availability, security, and scalability for modern applications.

Moreover it’s going to be a mess when we have to share state between non-connected components.

We can solve this problem by lifting user state up to the App component. But this can make our code messy when handling many states throughout the app.
For global state management we can use the React context API or libraries such as Redux or Recoil. In this post
In this post we do not go deeper into these topics and we will see how can we do this using unstated-next.
Unstated-next : Unstated-next is a simple light-weight library created based on React’s context API. We can use its simple API methods to manage global states throughout the app.
I’ll demonstrate the capabilities through a basic React app which has few components. Before proceeding, go ahead and create or clone a simple app.

Here in the app, Products.js and UserProfile.js represent separate pages and SideBar.js and TopBar.js components are used in both pages.
.webp)


.webp)
When was the last time airport lounge access actually felt premium?
Not the idea of it, but the experience itself. The long lines, the crowded seating, the rushed food service, the feeling that you paid for exclusivity and received congestion instead.
Premium credit cards have undeniably shaped consumer behavior in the United States. Lounge access, elite perks, and status-driven benefits became cultural currency. But as more consumers chased the same experiences, those luxuries quietly commoditized. In the race for Instagram-worthy moments, exclusivity diluted. What followed was predictable: increasingly complex loyalty rules, layered restrictions, and new tiers designed to separate “premium” from “super premium.”
Airlines began limiting lounge access by fare class. Priority Pass quietly restricted access for certain cardholders. American Express responded by building even more exclusive lounges. The ladder kept getting taller, while fewer people felt the climb was worth it.
That tension reached a breaking point in 2025. When American Express raised the Platinum card’s annual fee to an unprecedented $895, and Chase followed with increases across its Sapphire Reserve portfolio, it wasn’t just a pricing update. It was a signal. The traditional, bank-led loyalty model, built on escalating fees and increasingly narrow perks was starting to crack.
For a long time, consumers tolerated high fees because the benefits felt aspirational; airport lounges, hotel upgrades, travel credits, elite treatment. But recently, that sense of value has fractured. Increasingly, cardholders are questioning whether the perks match the price. Reports highlighted a rise in perk fatigue, with many users feeling that credits were too specific, too complicated to track, or simply irrelevant to their actual lifestyle. Once that emotional connection breaks, loyalty becomes fragile.
This shift isn’t just anecdotal. It’s reinforced by broader behavioral trends that reveal what consumers now expect from loyalty. One of the most telling insights comes from the Marqeta 2025 State of Payments Report, which found that 63% of consumers want unified rewards and loyalty across brands. That number disrupts the entire foundation of bank-owned loyalty. The message is clear: people are no longer interested in loyalty that is locked behind a single credit card or restricted to a specific ecosystem. They want loyalty that travels with them, across the brands they buy from daily, not just the banks they borrow from.
And if loyalty is shifting away from card-centric perks toward brand-centric value, then suddenly the playing field changes. Product brands, whether in retail, fintech, SaaS, wellness, lifestyle, or even digital services hold the advantage because they sit closer to the customer’s real behavior. They see how people spend, engage, subscribe, repeat, cancel, pause, return, and advocate. Banks can’t match that intimacy.
Research backs this up. Zendesk’s loyalty insights show that customers who feel genuinely appreciated and seen by a brand demonstrate higher retention and increased lifetime value. This is the kind of loyalty that isn’t transactional but emotional; rooted in recognition, not just rewards. When loyalty is embedded inside a product rather than bolted onto a credit card, it becomes something customers experience daily instead of something they check occasionally.
The timing of these trends couldn’t be more favourable for brands. Technology has removed the barriers that previously kept loyalty programs in the domain of large corporations. Modern loyalty architecture enables companies to weave personalized rewards, usage-based incentives, behavioural recognition, and even subtle gamification into the product experience without needing massive engineering teams or expensive infrastructure.
Brands now have the freedom to create loyalty ecosystems that match their identity and values, something banks have never been able to do. And because loyalty can be built on first-party data rather than third-party aggregations, brands can finally deliver the kind of relevance consumers crave.
For high-growth companies, this shift has significant financial implications. Loyal users don’t just buy more; they stay longer, engage more deeply, and share the product with others. Loyalty becomes a predictable revenue engine instead of an optional enhancement. And unlike card-based rewards, brand-owned loyalty strengthens the product itself. It becomes part of the journey, the story, and the relationship customers build over time.
At Nimi, we help brands build loyalty ecosystems designed for this new era. Our approach blends behavioural insights, modern UX, and data-driven reward engines to create loyalty apps that feel alive; adapting, learning, and responding to each customer. Whether through gamification, personalized journeys, or predictive recommendations, we build loyalty experiences that customers keep coming back to.
The future of loyalty isn’t about accumulating points. It’s about earning trust, creating emotional relevance, and building relationships that last. Personalization is no longer an enhancement, it’s the expectation. And the brands that embrace it now will define the loyalty landscape of 2026 and beyond.
If your loyalty program still looks like a points ledger instead of a relationship, it may be time to rethink the model.
We work with product brands that want to own loyalty directly; without bank rules, hidden trade-offs, or generic rewards. If you’re exploring what a modern, personalized loyalty app could look like for your product, let’s talk.