Skip to content
This repository was archived by the owner on May 6, 2023. It is now read-only.

Commit 401f0b3

Browse files
committed
initial commit; mvp status
0 parents  commit 401f0b3

17 files changed

+504
-0
lines changed

.gitignore

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
lerna-debug.log*
8+
9+
# Diagnostic reports (https://nodejs.org/api/report.html)
10+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11+
12+
# Runtime data
13+
pids
14+
*.pid
15+
*.seed
16+
*.pid.lock
17+
18+
# Directory for instrumented libs generated by jscoverage/JSCover
19+
lib-cov
20+
21+
# Coverage directory used by tools like istanbul
22+
coverage
23+
*.lcov
24+
25+
# nyc test coverage
26+
.nyc_output
27+
28+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29+
.grunt
30+
31+
# Bower dependency directory (https://bower.io/)
32+
bower_components
33+
34+
# node-waf configuration
35+
.lock-wscript
36+
37+
# Compiled binary addons (https://nodejs.org/api/addons.html)
38+
build/Release
39+
40+
# Dependency directories
41+
node_modules/
42+
jspm_packages/
43+
44+
# TypeScript v1 declaration files
45+
typings/
46+
47+
# TypeScript cache
48+
*.tsbuildinfo
49+
50+
# Optional npm cache directory
51+
.npm
52+
53+
# Optional eslint cache
54+
.eslintcache
55+
56+
# Microbundle cache
57+
.rpt2_cache/
58+
.rts2_cache_cjs/
59+
.rts2_cache_es/
60+
.rts2_cache_umd/
61+
62+
# Optional REPL history
63+
.node_repl_history
64+
65+
# Output of 'npm pack'
66+
*.tgz
67+
68+
# Yarn Integrity file
69+
.yarn-integrity
70+
71+
# dotenv environment variables file
72+
.env
73+
.env.test
74+
75+
# parcel-bundler cache (https://parceljs.org/)
76+
.cache
77+
78+
# Next.js build output
79+
.next
80+
81+
# Nuxt.js build / generate output
82+
.nuxt
83+
dist
84+
85+
# Gatsby files
86+
.cache/
87+
# Comment in the public line in if your project uses Gatsby and *not* Next.js
88+
# https://nextjs.org/blog/next-9-1#public-directory-support
89+
# public
90+
91+
# vuepress build output
92+
.vuepress/dist
93+
94+
# Serverless directories
95+
.serverless/
96+
97+
# FuseBox cache
98+
.fusebox/
99+
100+
# DynamoDB Local files
101+
.dynamodb/
102+
103+
# TernJS port file
104+
.tern-port
105+
106+
# Buxt ignores
107+
routes
108+
dev.ts
109+
*.http

.npmignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__tests__

__tests__/fixtures/default_export.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default async function() {
2+
//fixture
3+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export async function no_default_export() {
2+
//fixture
3+
}

__tests__/scan-paths.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { describe, it, expect } from "bun:test";
2+
import { join } from "path";
3+
import { cwd } from "process";
4+
import ScanPaths from "src/utils/ScanPaths";
5+
6+
const root = join(cwd(), "__tests__", "routes");
7+
8+
describe("Route mapper tests", () => {
9+
it("will recursively fetch the paths of files inside the 'routes' folder", async () => {
10+
const paths: Array<RoutePath> = [
11+
{ AbsolutePath: "messages.ts", FullPath: root + "/messages.ts", EffectiveRoute: "messages", },
12+
{ AbsolutePath: "messages/[id].ts", FullPath: root + "/messages/[id].ts", EffectiveRoute: "messages/[id]" },
13+
{ AbsolutePath: "messages/new_message.ts", FullPath: root + "/messages/new_message.ts", EffectiveRoute: "messages/new_message" },
14+
{ AbsolutePath: "user/[user]/[likes].ts", FullPath: root + "/user/[user]/[likes].ts", EffectiveRoute: "user/[user]/[likes]" },
15+
{ AbsolutePath: "user/[user].ts", FullPath: root + "/user/[user].ts", EffectiveRoute: "user/[user]" }
16+
];
17+
18+
const routePaths = await ScanPaths(root, "");
19+
20+
expect(JSON.stringify(routePaths)).toBe(JSON.stringify(paths));
21+
22+
expect(routePaths.length).toBe(5);
23+
24+
for (let x = 0; x < paths.length; x++) {
25+
expect(routePaths[x].FullPath).toBe(paths[x].FullPath);
26+
}
27+
28+
for (let x = 0; x < paths.length; x++) {
29+
expect(routePaths[x].AbsolutePath).toBe(paths[x].AbsolutePath);
30+
}
31+
});
32+
});

__tests__/validate-route.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { describe, it, expect } from "bun:test";
2+
import ValidateRoutes from "../src/utils/ValidateRoutes";
3+
4+
describe("Path validator tests", () => {
5+
it("will make sure the paths point to a module with a default export", async () => {
6+
//Cant actually do this with the current bun testing library?
7+
});
8+
});

bun.lockb

1.16 KB
Binary file not shown.

bunfig.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[bundle]
2+
entryPoints = ["./dist/index.ts"]
3+
4+
[dev]
5+
port = 3000

index.d.ts

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
declare type ScanPaths = (path: string, currentLevel: string) => Promise<Array<RoutePath>>
2+
declare type ValidateRoute = (routepath: RoutePath) => Promise<Route> | never;
3+
4+
declare type RequestMethod = "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD" | "PATCH";
5+
6+
declare class BuxtRequest {
7+
constructor(baseRequest: Request);
8+
9+
request: Request;
10+
method: string;
11+
path: string;
12+
matchPath: string;
13+
14+
query: { [key: string]: string };
15+
headers: { [key: string]: string };
16+
params: { [key: string]: string };
17+
18+
body: any;
19+
blob: any;
20+
21+
static buildRequest(req: Request): Promise<BuxtRequest>;
22+
}
23+
24+
export declare class BuxtResponse {
25+
response: Response;
26+
options: ResponseInit;
27+
isUsed: boolean;
28+
29+
headers(header: HeadersInit): BuxtResponse;
30+
31+
setStatusCode(code: number): BuxtResponse;
32+
setOptions(options: ResponseInit): BuxtResponse;
33+
setStatusText(text: string): BuxtResponse;
34+
setHeader(key: string, value: string): BuxtResponse;
35+
36+
getHeaders(): HeadersInit;
37+
getResponse(): Response;
38+
39+
send(body: any): void;
40+
json(body: any): void;
41+
}
42+
43+
export declare class BuxtServer {
44+
routes: string[];
45+
port: number;
46+
baseAddress: string;
47+
48+
private constructor(port: number);
49+
50+
static createServer(): Promise<BuxtServer>;
51+
52+
private registerRoutes(): Promise<void>;
53+
private handleRequest(): Promise<Response> | Response;
54+
55+
listen(): Promise<void>;
56+
stop(): void;
57+
}
58+
59+
export declare type RoutePath = {
60+
FullPath: string,
61+
AbsolutePath: string
62+
}
63+
64+
export declare type Route = {
65+
route: string,
66+
parameters: string[],
67+
delegate: (req: BuxtRequest, res: BuxtResponse) => Promise<BuxtResponse>;
68+
}

index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"use strict";
2+
3+
import { BuxtServer } from "./src/BuxtServer";
4+
import { BuxtRequest, BuxtResponse } from "buxt";
5+
6+
const factoryFunction = BuxtServer.createServer;
7+
8+
export { factoryFunction as CreateServer };
9+
10+
export type { BuxtResponse, BuxtRequest };
11+
export default BuxtServer.createServer;

package.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "buxt",
3+
"version": "0.0.1",
4+
"author": "Ryan C",
5+
"type": "module",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/mia-z/buxt"
9+
},
10+
"main": "index.ts",
11+
"types": "index.d.ts",
12+
"exports": {
13+
".": {
14+
"browser": {
15+
"default": "./index.ts"
16+
}
17+
}
18+
},
19+
"bugs": {
20+
"url": "https://github.com/mia-z/buxt/issues"
21+
},
22+
"license": "MIT",
23+
"scripts": {
24+
"dev": "bun dev.ts",
25+
"test": "bun wiptest test"
26+
},
27+
"devDependencies": {
28+
"bun-types": "^0.2.2"
29+
}
30+
}

src/BuxtRequest.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export default class BuxtRequest {
2+
request: Request;
3+
method: string;
4+
path: string;
5+
matchPath: string;
6+
7+
query: { [key: string]: string } = {};
8+
headers: { [key: string]: string } = {};
9+
params: { [key: string]: string } = {};
10+
11+
body: any;
12+
blob: any;
13+
14+
constructor(req: Request) {
15+
this.request = req;
16+
const { searchParams, pathname } = new URL(req.url);
17+
this.path = pathname;
18+
this.matchPath = pathname.slice(1, pathname.length);
19+
this.method = req.method;
20+
21+
searchParams.forEach((value, key) => {
22+
this.query[key] = value;
23+
});
24+
25+
req.headers.forEach((value, key) => {
26+
this.headers[key] = value;
27+
});
28+
}
29+
30+
static async buildRequest(req: Request): Promise<BuxtRequest> {
31+
const br = new BuxtRequest(req);
32+
const body = await req.json();
33+
req.arrayBuffer;
34+
br.body = body;
35+
br.blob = req.blob();
36+
return br;
37+
}
38+
}

src/BuxtResponse.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
export default class BuxtResponse {
2+
response: Response;
3+
options: ResponseInit = {};
4+
isUsed: boolean;
5+
6+
headers(header: HeadersInit): BuxtResponse {
7+
this.options.headers = header;
8+
return this;
9+
}
10+
11+
setStatusCode(code: number): BuxtResponse {
12+
this.options.status = code;
13+
return this;
14+
}
15+
16+
setOptions(options: ResponseInit): BuxtResponse {
17+
this.options = options;
18+
return this;
19+
}
20+
21+
setStatusText(text: string): BuxtResponse {
22+
this.options.statusText = text;
23+
return this;
24+
}
25+
26+
setHeader(key: string, value: string): BuxtResponse {
27+
if (!key || !value) {
28+
throw new Error('Headers key or value should not be empty');
29+
}
30+
31+
const headers = this.options.headers;
32+
if (!headers) {
33+
this.options.headers = { keys: value };
34+
}
35+
this.options.headers[key] = value;
36+
return this;
37+
}
38+
39+
getHeaders(): HeadersInit {
40+
return this.options.headers;
41+
}
42+
43+
getResponse(): Response {
44+
return this.response;
45+
}
46+
47+
send(body?: any): void {
48+
this.response = new Response(body, this.options);
49+
this.isUsed = true;
50+
}
51+
52+
json(body: any): void {
53+
this.response = Response.json(body, this.options);
54+
this.isUsed = true;
55+
}
56+
}

0 commit comments

Comments
 (0)