-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
781ff8f
commit e96c41c
Showing
4 changed files
with
121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,23 @@ | ||
# go.fart.tools | ||
|
||
[![GitHub Actions](https://github.com/FartLabs/rtx/actions/workflows/check.yaml/badge.svg)](https://github.com/FartLabs/rtx/actions/workflows/check.yaml) | ||
|
||
Link shortening service with Deno. | ||
|
||
## Contribute | ||
|
||
### Style | ||
|
||
Run `deno fmt` to format the code. | ||
|
||
Run `deno lint` to lint the code. | ||
|
||
### Test | ||
|
||
Run `deno test` to run the tests. | ||
|
||
Run `deno task start` to start the server. | ||
|
||
--- | ||
|
||
Developed with ❤️ [**@FartLabs**](https://github.com/FartLabs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,95 @@ | ||
// TODO: HTTP server setting and deleting shortlink data. | ||
// TODO: Add vscode settings file. | ||
import { createRouter } from "@fartlabs/rt"; | ||
import { go } from "go/go.ts"; | ||
|
||
class GoService { | ||
public constructor( | ||
private readonly kv: Deno.Kv, | ||
private readonly kvNamespace: Deno.KvKey = ["go"], | ||
) {} | ||
|
||
public async add( | ||
alias: string, | ||
destination: string, | ||
force = false, | ||
): Promise<void> { | ||
const collectionResult = await this.kv.get<string>(this.kvNamespace); | ||
const collection = collectionResult.value | ||
? JSON.parse(collectionResult.value) | ||
: {}; | ||
if (!force && collection[alias]) { | ||
throw new Error("Shortlink already exists."); | ||
} | ||
|
||
collection[alias] = destination; | ||
const result = await this.kv.atomic() | ||
.check(collectionResult) | ||
.set(this.kvNamespace, JSON.stringify(collection)) | ||
.commit(); | ||
if (!result.ok) { | ||
throw new Error("Failed to add shortlink."); | ||
} | ||
} | ||
|
||
public async delete(alias: string): Promise<void> { | ||
const collectionResult = await this.kv.get<string>(this.kvNamespace); | ||
const collection = collectionResult.value | ||
? JSON.parse(collectionResult.value) | ||
: {}; | ||
delete collection[alias]; | ||
const result = await this.kv.atomic() | ||
.check(collectionResult) | ||
.set(this.kvNamespace, JSON.stringify(collection)) | ||
.commit(); | ||
if (!result.ok) { | ||
throw new Error("Failed to delete shortlink."); | ||
} | ||
} | ||
|
||
public async collection(): Promise<Record<string, string>> { | ||
const collectionResult = await this.kv.get<string>(this.kvNamespace); | ||
return collectionResult.value ? JSON.parse(collectionResult.value) : {}; | ||
} | ||
} | ||
|
||
function isAuthorized(headers: Headers): boolean { | ||
const auth = headers.get("Authorization"); | ||
return auth === `Token ${Deno.env.get("GO_TOKEN")}`; | ||
} | ||
|
||
if (import.meta.main) { | ||
const kv = await Deno.openKv(); | ||
const goService = new GoService(kv); | ||
const router = createRouter() | ||
// TODO: Use rtx to define the routes. Use htx to define the HTML index page. | ||
.post("/api", async (ctx) => { | ||
if (!isAuthorized(ctx.request.headers)) { | ||
return new Response("Unauthorized", { status: 401 }); | ||
} | ||
|
||
const body = await ctx.request.json(); | ||
await goService.add(body.alias, body.destination, body.force); | ||
return new Response("Shortlink added.", { status: 201 }); | ||
}) | ||
.delete("/api", async (ctx) => { | ||
if (!isAuthorized(ctx.request.headers)) { | ||
return new Response("Unauthorized", { status: 401 }); | ||
} | ||
|
||
const body = await ctx.request.json(); | ||
await goService.delete(body.alias); | ||
return new Response("Shortlink removed.", { status: 200 }); | ||
}) | ||
.get("/:path*", async (ctx) => { | ||
const collection = await goService.collection(); | ||
const destination = go(ctx.url, collection); | ||
return new Response( | ||
`Going to ${destination.href}...`, | ||
{ | ||
status: 302, | ||
headers: { "Location": destination.href }, | ||
}, | ||
); | ||
}); | ||
|
||
Deno.serve((request) => router.fetch(request)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
{ | ||
"lock": false, | ||
"imports": { | ||
"go/": "./", | ||
"@fartlabs/rt": "jsr:@fartlabs/rt@^0.0.1", | ||
"@std/assert": "jsr:@std/assert@^0.221.0" | ||
}, | ||
"tasks": { | ||
"start": "deno run --unstable-kv --env -A cli/main.ts" | ||
} | ||
} |