-
Notifications
You must be signed in to change notification settings - Fork 6
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
0 parents
commit f6bee4f
Showing
41 changed files
with
2,182 additions
and
0 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,182 @@ | ||
# Functor | ||
|
||
Faster router in Deno (Working in the benchmarks) | ||
|
||
Functor was designed to be: | ||
|
||
- Independent | ||
- Fast | ||
- Scalable | ||
- Predictable | ||
|
||
Get started in 10 Minutes! | ||
## Get Functor and a server | ||
|
||
```typescript | ||
//Functor is just a router, so a server that give a Request and expect Response is needed | ||
|
||
import { serve } from "https://deno.land/std@0.159.0/http/server.ts"; | ||
|
||
// import fun | ||
|
||
import fun from "https://deno.land/x/functor/fun.ts"; | ||
``` | ||
## Give a path and a function | ||
|
||
```typescript | ||
// the function has to return a valid BodyInt or Promise<BodyInit> | ||
await serve( | ||
fun()([ | ||
{ | ||
path: "/", | ||
f: (_) => "hello world", | ||
}, | ||
]), | ||
{ port: 8080 }, | ||
); | ||
``` | ||
## Add parameters, a query, a status, or a header! | ||
|
||
```typescript | ||
// the router auto detect if you are using them, unless you send the arguments out of the scope | ||
// r: (arguments) => outOfScope(arguments), | ||
// you can add or remove them with "add", "delete" | ||
|
||
|
||
await serve( | ||
fun( | ||
{ hasName: "http://127.0.0.1:8080/" }, | ||
)([ | ||
{ | ||
path: "/test/:id", | ||
status: 201, | ||
header: new Headers(), | ||
r: (f) => f.param.id + " " + (f.query?.hello || ""), | ||
}, | ||
]), | ||
{ port: 8080, hostname: "127.0.0.1" }, | ||
); | ||
``` | ||
|
||
## Parameters | ||
|
||
Parameters must be chained, without gaps. | ||
|
||
```typescript | ||
// valid (It is important to note that the following routes are different) | ||
"/hello/:id" | ||
"/hello/:id/" | ||
"/hello/:id/:page/:time" | ||
"/hello/:id/:page/:time/" | ||
|
||
// invalid | ||
"/hello/:id/page/:time" | ||
"/hello/:id/page/:time/" | ||
|
||
|
||
``` | ||
|
||
|
||
## Do you need more control ? | ||
|
||
```typescript | ||
// use the type:"request" to return a Response or Promise<Response> | ||
// you can use params and query here too! | ||
|
||
|
||
await serve( | ||
fun( | ||
{ hasName: "http://127.0.0.1:8080/" }, | ||
)([ | ||
{ | ||
type: "request", | ||
path: "/abc", | ||
f: (f) => new Response(f.query?.hello || "abc"), | ||
}, | ||
]), | ||
{ port: 8080, hostname: "127.0.0.1" }, | ||
); | ||
``` | ||
## Do you need Functor just to route your function? I've got you covered! | ||
|
||
```typescript | ||
// use the type:"response" to return a Response or Promise<Response> | ||
await serve( | ||
fun( | ||
{ hasName: "http://127.0.0.1:8080/" }, | ||
)([ | ||
{ | ||
type: "response", | ||
path: "/", | ||
r: (_) => new Response("hello world"), | ||
|
||
}, ]), | ||
{ port: 8080, hostname: "127.0.0.1" }, | ||
); | ||
``` | ||
## Static file is natively build in functor! | ||
|
||
```typescript | ||
// "path" is relative to terminal | ||
// remove mime types with mime:false | ||
// add mime with extra: [ [header,extension]] | ||
await serve( | ||
fun( | ||
{ hasName: "http://127.0.0.1:8080/" }, | ||
)([ | ||
{ | ||
type: "static", | ||
name: "/s", | ||
path: "./", | ||
}, | ||
, ]), | ||
{ port: 8080, hostname: "127.0.0.1" }, | ||
); | ||
``` | ||
Thanks and have fun ~ | ||
|
||
|
||
|
||
|
||
# Specifications | ||
|
||
|
||
## Route options | ||
|
||
|
||
|
||
```typescript | ||
type funRouterOptions = { | ||
hasName?: string; | ||
paramsStartsWith?: string; | ||
notFound?: { (x: Request): Response }; | ||
badMethod?: { (x: Request): Response }; | ||
}; | ||
|
||
``` | ||
|
||
- **"hasName"**: is the name of the server, and it always has to finish with "/" | ||
, | ||
example: "http://127.0.0.1:8080/", the router will be 5% faster if a name is | ||
given. | ||
|
||
- **"paramsStartsWith"**: by default, a parameter is defined by ":" next to a | ||
"/", changing this value, will take the first character and check if it's | ||
follow by "/" to star a new parameter. | ||
|
||
- **"notFound"**: changes the default NOT_FOUND. | ||
|
||
- **"badMethod"**: changes the default BAD_METHOD. | ||
|
||
## Methods | ||
|
||
There are 4 methods | ||
|
||
```typescript | ||
type ParamsMethod = "GET" | "HEAD" | "POST" | "DELETE"; | ||
``` | ||
|
||
|
||
## License | ||
|
||
[CC BY-ND 4.0](https://creativecommons.org/licenses/by-nd/4.0/legalcode.txt) |
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,48 @@ | ||
import { | ||
ArrayFiler, | ||
ArraySwap, | ||
funRouterOptions, | ||
RouteTypes, | ||
} from "../types.ts"; | ||
|
||
export default (o?: funRouterOptions) => (a: RouteTypes[]): ArrayFiler => | ||
( | ||
(fl) => | ||
( | ||
(sp) => [ | ||
fl | ||
.map((x) => [x[1].split("/"), x[0], x[1], x[2]]) | ||
.map((x) => | ||
[x[0].length - 1, x[0], x[1], x[2], x[3]] as [ | ||
number, | ||
string[], | ||
RouteTypes[0], | ||
RouteTypes[1], | ||
RouteTypes[2], | ||
] | ||
) | ||
.map((x) => | ||
[ | ||
x[3] === "/" && o?.globalNotFound === true ? 0 : x[0], | ||
((y) => | ||
((a) => | ||
a.length <= 1 ? a.join("") : a[0] + a.slice(1).join("/"))( | ||
x[1] | ||
.filter((z) => z[0] !== y), | ||
))( | ||
typeof o?.paramsStartsWith === "string" | ||
? o?.paramsStartsWith | ||
: ":", | ||
), | ||
x[2], | ||
x[4], | ||
] as ArraySwap | ||
), | ||
sp, | ||
] | ||
)( | ||
a.filter((x) => typeof x[3] === "string") as RouteTypes[], | ||
) | ||
)( | ||
a.filter((x) => x[3] === false), | ||
); |
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,118 @@ | ||
import { | ||
ArrayFiler, | ||
funRouterOptions, | ||
ParamsMethod, | ||
RequestFunction, | ||
} from "../types.ts"; | ||
import badMethod from "../components/util/badMethod.ts"; | ||
import notFound from "../components/util/notFound.ts"; | ||
|
||
type InnerObj = [string, RequestFunction] | []; | ||
type InnerObjEmpty = [string, RequestFunction]; | ||
type Map = Record<number, Record<number, InnerObj[]>>; | ||
|
||
type Atlas = [ | ||
ParamsMethod[], | ||
number[][], | ||
string[][][], | ||
RequestFunction[], | ||
ArrayFiler[1], | ||
]; | ||
export default (_o?: funRouterOptions) => (a: ArrayFiler): Atlas => | ||
( | ||
(am) => | ||
( | ||
(ob) => | ||
( | ||
(il) => | ||
( | ||
(al) => | ||
( | ||
(ul) => [am, il, al, ul, a[1]] | ||
)( | ||
il.map( | ||
(x, i) => | ||
x.map( | ||
(y) => | ||
ob[i][y].map( | ||
(z) => [z[1]], | ||
), | ||
) as [RequestFunction][][], | ||
) | ||
.flat(3) | ||
.concat(a[1].map(([_, _a, x]) => x)) | ||
.concat(notFound) | ||
.concat(badMethod), | ||
) | ||
)( | ||
il.map( | ||
(x, i) => | ||
x.map( | ||
(y) => ob[i][y].map((x) => x[0]), | ||
), | ||
) as string[][][], | ||
) | ||
)( | ||
Object.keys(ob) | ||
.map((x) => Number(x)) | ||
.map( | ||
(x) => | ||
Object | ||
.keys(ob[Number(x)]) | ||
.map((y) => Number(y)), | ||
) as [number[]], | ||
) | ||
)( | ||
Object.fromEntries( | ||
am.map((x) => a[0].filter((y) => x === y[2])) | ||
.map( | ||
(x) => | ||
((p) => | ||
Object.fromEntries( | ||
p.map( | ||
(y) => [ | ||
y, | ||
( | ||
(za) => | ||
za[0][0] === "" | ||
? za | ||
.slice(1) | ||
.reduceRight( | ||
(acc, z) => acc.concat([z]), | ||
[za[0]], | ||
) | ||
.reverse() | ||
: za | ||
)( | ||
x | ||
.reduce( | ||
(acc, z) => | ||
z[0] === y | ||
? [...acc, [z[1], z[3]]] as InnerObjEmpty[] | ||
: acc, | ||
[] as InnerObjEmpty[], | ||
).sort((a, b) => b[0].length - a[0].length), | ||
), | ||
], | ||
), | ||
))( | ||
x.map((y) => y[0]) | ||
.reduce( | ||
(acc, y) => acc.includes(y) ? acc : acc.concat([y]), | ||
[] as number[], | ||
) as number[], | ||
), | ||
) | ||
.map( | ||
(x, i) => [i, x], | ||
), | ||
) as Map, | ||
) | ||
)( | ||
a[0] | ||
.reduce((acc: ParamsMethod[], am) => | ||
acc | ||
.includes(am[2]) | ||
? acc | ||
: [...acc, am[2]], []) as ParamsMethod[], | ||
); |
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,2 @@ | ||
export default (a: string[]) => | ||
((o) => (s: string) => o.indexOf(s[0]))(a.map((x) => x[0])); |
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,42 @@ | ||
import { funRouterOptions } from "../types.ts"; | ||
|
||
export default (_o?: funRouterOptions) => | ||
(m: number[][]) => | ||
(c: string[][][]) => | ||
((h) => | ||
((j) => | ||
h.map( | ||
(x, i) => | ||
((a) => | ||
m[i][0] === 1 || m[i][0] === 0 | ||
? a.map((y, a) => a === 0 && i === 0 ? 0 : y) | ||
: ([0].concat(a.map((x) => x + 1))).slice(0, -1))( | ||
x.map( | ||
(y, a, b) => | ||
y + (i === 0 | ||
? b.reduce( | ||
(acc, y, u) => a > u ? acc + y : acc, | ||
-1, | ||
) | ||
: j.reduce((acc, y, u) => u < i ? acc + y : acc) - 1), | ||
), | ||
), | ||
))( | ||
h.map( | ||
(x) => | ||
x | ||
.map( | ||
(y, i, a) => | ||
y + | ||
a.reduce( | ||
(acc, z, u) => i < u ? acc + z : acc, | ||
0, | ||
), | ||
) | ||
.reduce((acc, y) => y > acc ? y : acc, 0), | ||
), | ||
))( | ||
c.map( | ||
(x) => x.map((y) => y.length), | ||
), | ||
); |
Oops, something went wrong.