Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/heismanish/snapchat
A snapchat like application
https://github.com/heismanish/snapchat
nextauth nextjs14 shadcn typescript
Last synced: 30 days ago
JSON representation
A snapchat like application
- Host: GitHub
- URL: https://github.com/heismanish/snapchat
- Owner: Heismanish
- Created: 2024-05-24T04:18:29.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2024-09-04T17:55:19.000Z (4 months ago)
- Last Synced: 2024-09-06T01:15:41.090Z (4 months ago)
- Topics: nextauth, nextjs14, shadcn, typescript
- Language: TypeScript
- Homepage: https://snapchat-tau-rose.vercel.app
- Size: 719 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SnapChat-Web
## Getting Started
First, run the development server:
```bash
npm run dev
```Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
## Thing to learn:
### MONGODB and DB related:
1. Defining schema the typescript way(typesafe way):
```typescript
import { timeStamp } from "console";
import mongoose, { Model } from "mongoose";export interface IUser {
username: string;
fullname: string;
email: string;
avatar?: string;
}export interface IUserDocument extends IUser, Document {
createdAt: Date;
updatedAt: Date;
}const userSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
unique: true,
},
fullname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
avatar: {
type: String,
required: true,
},
},
{ timestamps: true }
);const User: Model =
mongoose.models?.User || mongoose.model("User", userSchema);export default User;
```2. Caching the connection:
```typescript
import mongoose, { Connection } from "mongoose";// here we have done this optimisation to check if we already have a cached connection
let cachedConnection: Connection | null = null;export async function connectToMongoDB() {
if (cachedConnection) {
console.log("Using cached MONGODB connection");
return cachedConnection;
}
try {
const conn = await mongoose.connect(process.env.MONGODB_URI as string);
cachedConnection = conn.connection;
console.log("DB CONNECTED");
return cachedConnection;
} catch (error) {
console.log(error);
throw error;
}
}
```## Server Actions:
![Server Auth Theory](./ServerAuth.png)
- **Inline Server Actions:** (can't be used in client components)
```typescript
export default function LoginCard() {
const authAction = async () => {
"use server";
await signIn("github");
};return (
<>
New To SnapNext?
Sign Up
>
);
}
```## Error Files:
- The error.tsx file can be used to define a UI boundary for a route segment. It serves as a catch-all for unexpected errors and allows you to display a fallback UI to your users.
- There are a few things you'll notice about the code above:
- "use client" - error.tsx needs to be a Client Component.
- It accepts two props:1. error: This object is an instance of JavaScript's native Error object.
2. reset: This is a function to reset the error boundary.When executed, the function will try to re-render the route segment.
**Example:**
```typescript
"use client";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
Something went wrong!
{error.message}
reset()
}
>
Try again
);
}
```## Converting string value to boolean:
Here "selectedFile" is a string value which we have converted to a boolean.
```typescript
```
## DB Setup:
![DB Setup](./DB.png)
### Mongoose things:
- **exec():**
**When you use exec() to run a query, you get exactly a promise as response.**
**exec()** function returns a promise, that you can use it with then() or async/await to execute a query on a model "asynchronous". So the question is "If I can just use user = await UserModel.find() and it works currectly, so why should I use exec() function?".- **Internal error: Error: Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.**
**Solution:** convert to string before passing to client component```typescript
return JSON.parse(JSON.stringify(newMessage));
```- ```typescript
const chat: IChatDocument | null = await Chat.findOne({
participants: { $all: [authUserId, otherUserId] },
}).populate({
path: "messages",
populate: { path: "sender", model: "User", select: "fullname" },
});
```**Exlaination:**
- ` .populate(...)`: This method is used to automatically replace the specified paths in the document with documents from other collections. It's a way to perform **JOIN-like operations in MongoDB**.
- `{ path: "messages" }`: This indicates that the messages field, which is likely an array of message references (IDs), should be populated with the actual message documents.
- `populate: { path: "sender", model: "User", select: "fullname" }`: This further populates the sender field within each message. It indicates that the sender field, which is a reference to a user document, should be populated with data from the User model, but only including the fullname field of the user.## Sending Image as "blob":
```typescript
const handleSendMessage = async (imgUrl: string) => {
setIsLoading(true);
try {
// fetch the image and convert it to a blob
const blob = await fetch(imgUrl).then((resolve) => resolve.blob());
// from blob, the url of the image is generated
const dataUrl = await readFileAsDataURL(blob);
// message is sent as an image
await sendMessageAction(id, dataUrl, "image");
} catch (error) {
console.log("Error sending emoji: ", error);
throw error;
} finally {
setIsLoading(false);
}
};
```**Explaination:**
Here, fetch(imgUrl) is called to initiate an HTTP request to the provided image URL (imgUrl). The fetch function returns a promise that resolves to a Response object representing the response to the request.
`.then((response) => response.blob()):` This code takes the response and calls the .blob() method on it. The .blob() method extracts the response body as a Blob object, which is a binary representation of the data.