# Deno crash course
###### tags: `deno` `typeScript`
> [TOC]
[Deno](https://deno.land/)
# Deno CLI

# Deno standard library
[Library source](https://deno.land/std@0.158.0?source)
```
deno run <fileName or URL>
```


# Install scribe
http/server.ts

deno runs in the sandbox and we need to add these flags if we want certain permission.
So this actually requires read permission and network permission.
So, we have to run it with some flag

We can also install it

# Import Library
<!-- How can we use something from the standard library -->
The example of how to use standard library library module
```typescript
import { dayOfYear, currentDayOfYear } from "https://deno.land/std@0.158.0/datetime/mod.ts";
console.log(dayOfYear(new Date("1992-11-11")));
```
# File
## Create a File
Our mission are creating the file called meowhecker.txt
### Create an encoder and Texts
```typescript=
const encoder = new TextEncoder //utf-8
const greetText = encoder.encode("Hello \n meowhecker 大人")
```
### Write and create it
```typescript
//write file
await Deno.writeFile("greet.txt", greetText)
```
Await is used to wait for the promise(only can be used in the async function
)
use write file method on the deno namespace
### Run
```
deno run --allow-write .\creatFile.ts
```
## Read the File
```
let file = await Deno.open("greet.txt")
await Deno.copy(file, Deno.stdout)
file.close()
```

# REST API
## [Create Http Server](https://deno.land/std@0.60.0/http/mod.ts?s=serve)
```typescript
import { serve } from "https://deno.land/std@0.60.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
req.respond({ body: "Hello World\n" });
}
```
## build API
### initialize app
```typescript
import {Application, Router} from 'https://deno.land/x/oak/mod.ts'
// initial APP
const app = new Application()
const port = 3000
console.log("Server running on port ${port}")
await app.listen({port})
```
### Set up router (middleWare
```
const router = new Router()
//for the middleware
app.use(router.routes())
app.use(router.allowedMethods())
//Router
router.get('/api/test1', ({response}:{response:any}) => {
response.body ="meowhecker api"
})
```
### Source
```
import {Application, Router} from 'https://deno.land/x/oak/mod.ts'
const port = 3000
// initial APP
const app = new Application()
const router = new Router()
//for the middleware
app.use(router.routes())
app.use(router.allowedMethods())
//Router
router.get('/api/test1', ({response}:{response:any}) => {
response.body ="meowhecker api"
})
console.log(`Server running on port ${port}`)
await app.listen({port})
```
### Result

### Separate router from server.ts
server.ts
```typescript
import {Application} from 'https://deno.land/x/oak/mod.ts'
import router from "./router.ts"
const port = 3000
// initial APP
const app = new Application()
//for the middleware
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Server running on port ${port}`)
await app.listen({port})
```
router.ts
```typescript
import {Router} from 'https://deno.land/x/oak/mod.ts'
const router = new Router()
//Router
router.get('/api/test1', ({response}:{response:any}) => {
response.body ="meowhecker api"
})
export default router //pass router
```
## Controller
Separate file for Route function
Create controller

```typescript
// Declare data type
interface Guns{
id:string,
name:string,
description:string,
price:number
}
let guns:Guns[] = [
{
id:"1",
name: "ak47",
description:"Refle",
price:2500
}
,
{
id:"2",
name: "Kar-98",
description:"Sniper Refle",
price:4500
}
,
{
id:"3",
name: "MP5",
description:"summachine gun",
price:1500
}
]
```
### Separate the interface
However, we could use export and create the file which called type.ts
In this way, we could import it in anywhere.
type.ts
```typescript
export interface Guns{
id:number,
name:string,
description:string,
price:number
}
```
guns.ts
```typescript
import {Guns} from "../type"
let guns:Guns[] = [
{
id:1,
name: "ak47",
description:"Refle",
price:2500
}
,
{
id:2,
name: "Kar-98",
description:"Sniper Refle",
price:4500
}
,
{
id:3,
name: "MP5",
description:"summachine gun",
price:1500
}
]
```
### Get all guns(Controller)
controller function is going to hooked to our route
```typescript
// GET Guns
const getGuns = ({response}:{response:any}) =>{
response.body={
success:true,
data:guns
}
}
export {getGuns}
```
```typescript
//Router
router.get('/api/Guns', getGuns)
```

### API router
API Router
router.ts
```typescript
router.get('/api/Guns', getGuns)
.get('/api/getGun/:id', getGun)
.post('/api/addGun', addGun)
.put('/api/updateGun/:id', updateGun)
.delete('/api/deleteGun/:id', deleteGun)
```
controller (test)
```typescript
//Controller function
// GET Guns
const getGuns = ({response}:{response:any}) =>{
response.body={
success:true,
data:guns
}
}
//Get single Gun
const getGun = ({response}:{response:any}) =>{
response.body="get single"
}
//Add a Gun
const addGun = ({response}:{response:any}) =>{
response.body="Post request"
}
//Update a Gun
const updateGun = ({response}:{response:any}) =>{
response.body="Put resequest"
}
//Delete a Gun
const deleteGun = ({response}:{response:any}) =>{
response.body="delete request"
}
export {getGuns,getGun,addGun,updateGun,deleteGun}
```
### Get a Single gun
We need to grab on to this ID that's pass in, So in addition to response we want "params"
#### To get a single gun
```typescript
const gun:Guns | undefined = Guns.find(g => g.id === params.id)
```
guns.find: for each gun we want to get the gun where the id equal to to the params ID
```typescript
const getGun = ({response, params}:{response:any, params:{id:string}}) =>{
const gun:Guns | undefined = guns.find(p => p.id === params.id)
//if gun was found
if(gun){
response.status = 200
response.body = {
success: true,
data: gun
}
} else{
response.status =404,
response.body = {
success: false,
msg: "no message found"
}
}
}
```

## Add the single Gun
To get the the data that's from the client we have to pass in () here request
if await has squiggly line. because this is no longer scope or top-level, we have to add a sync here
There has a bug with the generate function, I didn't know how to solve it. I think probably the problem with the version is too old(v4)
```typescript
const addGun = async({response, request}:{response:any, request:any}) =>{
// response.body="Post request"
const body = await request.body() //body method() which returns a promis we need to use await
if(!request.hasBody){
response.status=400
response.body={
success: false,
msg: "No data"
}
}else{
const gun: Guns = body.value // the value we're going to assign to this variable(json)
//create the ID, because you don't create the ID from the client, it get added by the database
// gun.id=v4.generate()
//so once we have the gun constructed, we'll go ahead and take the product array and push on to it,
guns.push(gun)
response.status= 201 //201 means everything went okay and something got create
response.body ={
success: true,
data: gun
}
}
}
```
## Update the gun
```typescript
const updateGun = async({params, request, response}:{params:{id:string}, request:any, response:any}) =>{
const gun:Guns | undefined = guns.find(p => p.id === params.id) //getting the gun by params ID
//if gun was found
if(gun){
const body = await request.body()
const updateData : {name?:string; description?:string; price?:number} =body.value
// using map to updata
guns = guns.map(p=> p.id === params.id ? {...p,...updateData}:p )
response.status = 200
response.body={
success:true,
data: guns
}
} else{
response.status =404
response.body = {
success: false,
msg: "no message found"
}
}
```
## Delete guns

```typescript
const deleteGun = ({params,response}:{params:{id:string},response:any}) =>{
guns = guns.filter(p => p.id !== params.id)
response.body = {
success: true,
msg:"guns removed"
}
}
```
# Solve Error

the error is header didn't carry the contain od the content-type, So now we just adding it. the problem is going to be solve.

# VSC extension
