.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)
Users sign up, earn something once, and quietly disengage. Not because the product is broken, but because the incentive logic never earns a permanent place in how people actually make spending decisions.
This problem is especially visible in the U.S. right now. Consumers are overloaded with loyalty programs, yet engagement is collapsing. Statista data shows the average American is enrolled in five or more rewards programs, but actively uses fewer than half. The rest sit idle, inflating dashboards while delivering little real leverage.
We saw this pattern up close while building modern rewards systems for a Top 10 Auto-Rewards Fintech Platform in the U.S. and GolfCard.
Different industries. Different stages.
Same hard lesson: most rewards systems are designed for companies, not for human behavior.
Why Rewards Systems Matter More Than Ever
Rewards are no longer a growth experiment. They’re infrastructure.
In the U.S., spending continues to shift toward card-linked offers, embedded finance, and instant-value incentives. McKinsey reports that companies with high-performing loyalty programs grow revenue 2–3x faster than competitors, largely because rewards now influence where customers spend; not just how often.
At the same time, expectations have hardened:
This tension shaped every architectural decision we made.
What Building Two Very Different Rewards Platforms Actually Taught Us
Abstract Rewards Kill Engagement
In the auto-rewards fintech platform, users didn’t only care about “points.” They cared about real money off real expenses; fuel, maintenance, insurance, tolls.
GolfCard surfaced the same truth from a different angle, even before full launch. While still operating through a waitlist, early demand wasn’t only driven by generic discounts. It was driven by status and access: priority tee times, member-only pricing, and experiences that felt earned, not promotional.
Harvard Business Review has documented this clearly: experiential, immediately understandable rewards outperform deferred point-based systems. If a reward needs explanation, it’s already losing.
Breakage Is No Longer a Viable Strategy
Traditional loyalty systems quietly rely on breakage; rewards that are earned but never redeemed. That model doesn’t survive modern transparency.
Gartner research shows 73% of consumers abandon loyalty programs they believe are intentionally difficult to redeem. Once trust erodes, no campaign brings it back.
Across both platforms, we deliberately designed for expected redemption, not avoidance:
The result was counterintuitive but consistent: easier redemption increased long-term value. Trust compounds faster than friction ever could
Personalization Is an Architecture Problem
“Personalized rewards” is one of the most overused phrases in fintech. Very few systems can actually deliver it.
True personalization required rethinking data flows entirely:
Statista reports that 80% of U.S. consumers are more likely to engage with personalized experiences, but relevance is the real constraint. Poor personalization doesn’t feel neutral, it feels invasive.
The key insight: Rules engines outperform static campaigns. Event-driven rewards systems change engagement structurally, not incrementally.
Merchant Economics Decide Everything
Here’s what many founders underestimate: merchants, not users, decide whether rewards systems survive.
For the auto-rewards fintech platform, success depended on:
For GolfCard, even at the waitlist stage, the challenge was helping courses monetize unused capacity without devaluing premium tee times.
Stripe’s research on embedded incentives confirms this: systems that align platform, merchant, and user incentives outperform flat discounts over time. We saw that alignment determine which features scaled, and which disappeared.
What the Data Is Really Saying
Modern rewards systems are financial products disguised as engagement features. Treat them like marketing gimmicks, and they’ll behave like disposable campaigns.
What This Means for Founders and Operators
If you’re building or rethinking a rewards system, especially for a U.S. market; here’s the uncomfortable truth:
Rewards logic is strategy.
The strongest platforms we worked on, whether fully live or validating demand through waitlists didn’t ask, “How do we reward users?”
They asked: “What behaviour are we economically willing to reinforce?”
That question eliminates most bad ideas instantly.
Ready to Build Rewards That Actually Work?
Most teams fail because modern rewards systems sit at the intersection of finance, behavior, data, and merchant economics and very few teams design for all four.
We’ve built rewards infrastructure for live fintech platforms processing real transactions. We know what breaks under load, what users ignore, and what quietly compounds value.
If you’re building:
and you want it designed as infrastructure, not a marketing add-on:
Nimi helps founders and operators design, build, and scale modern rewards systems that actually get used.
Explore our work or start a conversation at https://www.nimidev.com/
Because rewards aren’t about giving more. They’re about reinforcing the right behaviour, at scale.