Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
M0hammedImran committed Jul 1, 2022
0 parents commit 8ed9bc7
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"deno.enable": true,
"cSpell.words": [
"preact"
]
}
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# fresh project

### Usage

Start the project:

```
deno task start
```

This will watch the project directory and restart as necessary.
6 changes: 6 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"tasks": {
"start": "deno run -A --watch=static/,routes/ dev.ts"
},
"importMap": "./import_map.json"
}
5 changes: 5 additions & 0 deletions dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env -S deno run -A --watch=static/,routes/

import dev from "$fresh/dev.ts";

await dev(import.meta.url, "./main.ts");
20 changes: 20 additions & 0 deletions docker-compose.postgres.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: '3.8'

services:
postgres:
container_name: postgres
image: postgres:14.3-alpine
restart: always
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: freshapp
ports:
- '5432:5432'
volumes:
- 'pg_data:/var/lib/postgresql/data/'


volumes:
pg_data:
driver: local
22 changes: 22 additions & 0 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// DO NOT EDIT. This file is generated by fresh.
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.

import * as $0 from "./routes/api/todos/[id].ts";
import * as $1 from "./routes/api/todos/index.ts";
import * as $2 from "./routes/index.tsx";
import * as $$0 from "./islands/Counter.tsx";

const manifest = {
routes: {
"./routes/api/todos/[id].ts": $0,
"./routes/api/todos/index.ts": $1,
"./routes/index.tsx": $2,
},
islands: {
"./islands/Counter.tsx": $$0,
},
baseUrl: import.meta.url,
};

export default manifest;
11 changes: 11 additions & 0 deletions import_map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"imports": {
"$fresh/": "https://deno.land/x/[email protected]/",
"$zod/": "https://deno.land/x/[email protected]/",
"$denodb/": "https://deno.land/x/[email protected]/",
"preact": "https://esm.sh/[email protected]",
"preact/": "https://esm.sh/[email protected]/",
"preact-render-to-string": "https://esm.sh/[email protected][email protected]"
}
}

23 changes: 23 additions & 0 deletions islands/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/** @jsx h */
import { h } from "preact";
import { useState } from "preact/hooks";
import { IS_BROWSER } from "$fresh/runtime.ts";

interface CounterProps {
start: number;
}

export default function Counter(props: CounterProps) {
const [count, setCount] = useState(props.start);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count - 1)} disabled={!IS_BROWSER}>
-1
</button>
<button onClick={() => setCount(count + 1)} disabled={!IS_BROWSER}>
+1
</button>
</div>
);
}
9 changes: 9 additions & 0 deletions main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference no-default-lib="true" />
/// <reference lib="dom" />
/// <reference lib="dom.asynciterable" />
/// <reference lib="deno.ns" />
/// <reference lib="deno.unstable" />

import { start } from "$fresh/server.ts";
import manifest from "./fresh.gen.ts";
await start(manifest);
16 changes: 16 additions & 0 deletions models/Todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { DataTypes, Model } from "$denodb/mod.ts";

export class Todo extends Model {
static table = 'todos';
static timestamps = true;

static fields = {
id: { primaryKey: true, autoIncrement: true },
text: DataTypes.STRING,
completed: DataTypes.BOOLEAN,
};

static defaults = {
completed: false,
};
}
60 changes: 60 additions & 0 deletions routes/api/todos/[id].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { HandlerContext } from '$fresh/server.ts';
import { Todo } from '../../../Models/Todo.ts';
import { db } from '../../../utils/db.ts';
import * as zod from 'https://deno.land/x/[email protected]/mod.ts';

const idSchema = zod.number();

const todoSchema = zod.object({
completed: zod.boolean(),
});

export async function handler(req: Request, ctx: HandlerContext) {
try {
if (req.method === 'GET') {
const id = idSchema.parse(Number(ctx.params.id));

const data = await Todo.find(id);

return new Response(JSON.stringify({ data }), {
headers: { 'Content-Type': 'application/json' },
});
}

if (req.method === 'PATCH') {
const id = idSchema.parse(Number(ctx.params.id));

const todo = todoSchema.parse(await req.json());

await Todo.where({ id }).update(todo);
const data = await Todo.find(id);

return new Response(JSON.stringify({ data }), {
headers: { 'Content-Type': 'application/json' },
});
}

return new Response(undefined, {
headers: { 'Content-Type': 'application/json' },
status: 405,
statusText: 'Method Not Allowed',
});
} catch (error) {
if (error instanceof zod.ZodError) {
return new Response(JSON.stringify({ error, message: 'Invalid Id' }), {
headers: { 'Content-Type': 'application/json' },
status: 400,
statusText: 'Bad Request',
});
}

return new Response(JSON.stringify({ error }), {
headers: { 'Content-Type': 'application/json' },
status: 500,
statusText: 'Internal Server Error',
});
} finally {
await db.close();
}
}

40 changes: 40 additions & 0 deletions routes/api/todos/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { HandlerContext } from '$fresh/server.ts';
import { Todo } from '../../../models/Todo.ts';
import { db } from '../../../utils/db.ts';
import { TodoInputSchema } from '../../../utils/zodSchema.ts';

export async function handler(req: Request, _ctx: HandlerContext) {
try {
if (req.method === 'GET') {
const data = await Todo.all();
return new Response(JSON.stringify({ data }), {
headers: { 'Content-Type': 'application/json' },
});
}

if (req.method === 'POST') {
const body = await req.json();
const todo = TodoInputSchema.parse(body);
const data = await Todo.create({ ...todo });

return new Response(JSON.stringify({ data }), {
headers: { 'Content-Type': 'application/json' },
});
}

return new Response(undefined, {
headers: { 'Content-Type': 'application/json' },
status: 405,
statusText: 'Method Not Allowed',
});
} catch (error) {
return new Response(JSON.stringify({ error }), {
headers: { 'Content-Type': 'application/json' },
status: 400,
statusText: 'Bad Request',
});
} finally {
await db.close();
}
}

26 changes: 26 additions & 0 deletions routes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/** @jsx h */
import { h } from 'preact';

import { Handlers } from '$fresh/server.ts';
import { Todo } from '../models/Todo.ts';

export const handler: Handlers<Todo[] | null> = {
async GET(_, ctx) {
const todos = await Todo.select('id', 'text', 'completed').orderBy('id').all();
return ctx.render(todos);
},
};

export default function Home({ data }: { data: Todo[] | null }) {
return (
<div>
{data?.map((todo) => (
<div key={todo.id}>
<h1>Todo: {todo.text}</h1>
<p>Completed: {String(todo.completed)}</p>
</div>
))}
</div>
);
}

Binary file added static/favicon.ico
Binary file not shown.
6 changes: 6 additions & 0 deletions static/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions utils/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Database, PostgresConnector } from 'https://deno.land/x/[email protected]/mod.ts';
import { Todo } from "../Models/Todo.ts";

const connection = new PostgresConnector({
host: 'localhost',
port: 5432,
username: 'user',
password: 'password',
database: 'freshapp',
});

export const db = new Database(connection);

db.link([Todo])

14 changes: 14 additions & 0 deletions utils/zodSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { z } from '$zod/mod.ts';


export const TodoInputSchema = z.object({
text: z.string(),
completed: z.boolean(),
});


export const TodoSchema = TodoInputSchema.extend({
id: z.number(),
createdAt: z.string(),
updatedAt: z.string(),
});

0 comments on commit 8ed9bc7

Please sign in to comment.