Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/invisal/khmercoders
https://github.com/invisal/khmercoders
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/invisal/khmercoders
- Owner: invisal
- Created: 2024-02-10T01:31:57.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-03-07T01:25:38.000Z (10 months ago)
- Last Synced: 2024-10-19T07:06:22.785Z (3 months ago)
- Language: TypeScript
- Homepage: https://khmercoders.vercel.app
- Size: 354 KB
- Stars: 10
- Watchers: 2
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# KhmerCode Blog
A unified blogging platform for khmer coders.
### Setup
1. Clone the repo
2. Update the `.env`
You can create a free turso account use a serverless Squealite DB.
Where you need to add into your `.env`:- `DATABASE_URL`
- `DATABASE_AUTH_TOKEN`Or you can create a `dev.db` file in the root directory then in your `.env` just add
`DATABASE_URL="file:./dev.db"`, you can change the database name to wutever u like3. Installation and Development
```sh
# oh u dont have pnpm?
corepack enable pnpm# use it, it's faster 😂
# Install deps
pnpm install# Run migration
pnpm run db:migrate# Run dev server
pnpm dev
```### DB and Schema
You can find the db tables and schemas in `@/lib/db`, there we define the table for our database
and we directly infer validation schema from it.You may check the docs for the ORM and Validator:
- [DrizzleORM](https://orm.drizzle.team)
- [Zod](https://zod.dev/)```ts
// This is a reference from the `Article` schema// 1. First we define the table
export const articles = sqliteTable("articles", {
id: text("id")
.primaryKey()
// this auto generate UUID using our custom nanoid function
.$defaultFn(() => nanoid()),userId: text("user_id")
.notNull()
// this tie the relationship back to `users`
.references(() => users.id),title: text("title").notNull(),
description: text("description"),
content: text("content").notNull(),
cover: text("cover"),// auto generate timestamps
createdAt: text("created_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
updatedAt: text("updated_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
});// 2. We define the validation schema
// First we create a base schema for the articles table
// Note that we omit the timestamps from the base schema
const baseSchema = createSelectSchema(articles).omit(timestamps);// Then we create the insert schema which also omits the timestamps
export const insertArticleSchema =
createInsertSchema(articles).omit(timestamps);// This is the schema we use to validate on the client side
// it doesnt need to include the id or userId
export const insertArticleParams = baseSchema.extend({}).omit({
id: true,
userId: true,
});// The update schema is the same as the base schema
export const updateArticleSchema = baseSchema;// Same thing here we exclude the userId from the params cuz this will be used client side
export const updateArticleParams = baseSchema.extend({}).omit({
userId: true,
});// 3. We infer the type and export them
// Types for articles - used to type API request params and within Components
export type Article = typeof articles.$inferSelect;
export type NewArticle = z.infer;
export type NewArticleParams = z.infer;
export type UpdateArticleParams = z.infer;
```### Auth
Currently we export 2 functions for checking Auth
`checkAuth` and `getUserAuth`
- `checkAuth(): Promise` will redirect to `/sign-in` if not logged in
- `getUserAuth(): Promise` will return `Session`, you can handle redirect manually```ts
// Example// write/page.tsx
const WritePage = async () => {
// this will check for auth and redirect if not logged in
await checkAuth()return (
// ...
)
}// index/page.tsx
const HomePage = async () => {
const session = await getUserAuth()if (!session.session) {
// meaning not logged in
// you can do wutever u want here
// return redirect('/sign-in')
}// you can check the session which contain some user information
return (
{JSON.stringify(session.session, null, 2)}
)
}```
### Convention
- filename should be in `kebab-case`
- variable name should be in `camelCase`
- constant should be in `UPPERCASE`
- component should be in `PascalCase`### Docs
- [DrizzleORM](https://orm.drizzle.team)
- [Zod](https://zod.dev)
- [Lucia Auth](https://lucia-auth.com/)
- [EditorJS](https://editorjs.io/)
- [Shadcn UI](https://ui.shadcn.com)
- [Radix Primitive](https://www.radix-ui.com/primitives)More docs to come...